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 - Web Development

1797 Articles
article-image-getting-started-bootstrap
Packt
14 Mar 2014
5 min read
Save for later

Getting Started with Bootstrap

Packt
14 Mar 2014
5 min read
(For more resources related to this topic, see here.) Why use Bootstrap? Bootstrap contains a top-notch, responsive mobile-first grid, which allows you to implement your design in a breeze; it comes with ready-made styles for typography, navigation, tables, forms, buttons, and more. Bootstrap also includes some jQuery plugins, such as Modal, Dropdown, Tooltip, and Carousel, which come in handy quite often. Today, you can use Bootstrap to throw together quick prototypes or guide the execution of more sophisticated designs and larger engineering efforts. In other words, Bootstrap is a very simple way to promote quick, clean and highly usable applications. – Mark Otto, creator of Bootstrap Even though Bootstrap comes with all these features, none of them actually get in the way of further customization. Bootstrap is very easy to extend, especially if you use LESS instead of traditional CSS. At its core, Bootstrap is just CSS, but it's built with Less, a flexible pre-processor that offers much more power and flexibility than regular CSS. With Less, we gain a range of features like nested declarations, variables, mixins, operations, and color functions. – Mark Otto, creator of Bootstrap Next, you will learn about the advantages and disadvantages of using Bootstrap. Bootstrap pros and cons As with many things, using Bootstrap too has its pros and cons. Let us list some important things that you will need to know when you decide whether or not to use Bootstrap in your project. The pros are as follows: Cross-browser support: Bootstrap works on all the latest desktop and mobile browsers. While older browsers may display Bootstrap differently with respect to styles, it is still fully functional in legacy browsers such as Internet Explorer 8. Easy to customize: Bootstrap is easy to customize, especially with the use of LESS. You can also leave out parts that you do not need, that is, you can use only its grid and leave out all the components, or you can leave out the grid and use its components. Encourages using LESS : Bootstrap is written in LESS, a dynamic style sheet language that is compiled into CSS, which gives it a lot of flexibility. You can take advantage of this if you use LESS to write your styles. Supports useful jQuery plugins: Bootstrap comes with many useful jQuery plugins that can come handy in many situations. The quality of the plugins is not the best, and they usually work best when you do not customize them at all. Many custom jQuery plugins available: There is a wide range of jQuery plugins that extend Bootstrap, for example, X-editable, Wysihtml5, and the jQuery File Upload. Mobile-first: Bootstrap has been mobile-first since Version 3.0. This means that the grid starts out stacked and is floated using media queries when the screen width grows. The cons are as follows: jQuery plugins are hard to customize : The jQuery plugins that come with Bootstrap are often hard to customize, and many argue that they are not written using best practices, so it can be challenging to work with the source code at times. Usually, the plugins work in the most common cases but they come up short when you try to customize them a bit. Many Bootstrap sites end up looking alike: It is unfortunate that many sites that are built with Bootstrap look exactly the same, but you can avoid this by using a custom theme or creating your own theme. Creating your first Bootstrap project Now that you know when it is suitable to use Bootstrap, you are ready to start your first Bootstrap project. Perform the following steps to get started: Create a new folder for your Bootstrap project inside your document root. You can call it bootstrap-app. Pick up the latest version of Bootstrap from http://getbootstrap.com and unpack it into your project directory. Create a new HTML document, add the following contents, and save it in your project directory as index.html in the following manner: <!DOCTYPE html> <html> <head> <title>Hello from Bootstrap</title> <!-- Ensure proper rendering and touch zooming on mobile devices --> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href="css/bootstrap.min.css" rel="stylesheet"> <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!--[if lt IE 9]> <script src ="https://oss.maxcdn.com/libs/html5shiv/3.7.0/ html5shiv.js"> </script> <script src ="https://oss.maxcdn.com/libs/respond.js/1.3.0/ respond.min.js"> </script> <![endif]--> </head> <body> <h1>Hello, world!</h1> </body> </html> You can omit html5shiv.js and respond.js if you don't wish to support older versions of Internet Explorer. Let us look at the following reasons why we included all those CSS and JavaScript files: bootstrap.min.css: It is the minified version of the Bootstrap CSS styles html5shiv.js: It adds HTML5 support to older browsers respond.min.js: It adds media query support to older browsers Navigate to your project directory using your favorite web browser; you should see your project in action as shown in the following screenshot. Not too impressive, but do not worry, you will soon add more to it. For more information on how to get started with Bootstrap, refer to the Getting started page on the official site at http://getbootstrap.com/getting-started/. Summary In this article, you learned about the pros and cons of Bootstrap, as well as how to decide whether or not to use Bootstrap in a project. You also learned how to create a very simple Bootstrap project. Resources for Article: Further resources on this subject: Bootstrap 3.0 is Mobile First [Article] Downloading and setting up Bootstrap [Article] Top Features You Need to Know About – Responsive Web Design [Article]
Read more
  • 0
  • 0
  • 2892

article-image-form-handling
Packt
20 Feb 2014
22 min read
Save for later

Form Handling

Packt
20 Feb 2014
22 min read
(For more resources related to this topic, see here.) Collecting user data is a basic function of many websites and web applications, from simple data collection techniques such as registration or login information, to more complex scenarios such as payment or billing information. It is important that only relevant and complete information is collected from the user. To ensure this, the web developer must enforce validation on all data input. It is also important to provide a good user experience while enforcing this data integrity. This can be done by providing useful feedback to the user regarding any validation errors their data may have caused. This article will show you how to create an attractive web form that enforces data integrity while keeping a high-quality user experience. A very important point to note is that any JavaScript or jQuery validation is open to manipulation by the user. JavaScript and jQuery resides within the web browser, so a user with little knowledge can easily modify the code to bypass any client-side validation techniques. This means that client-side validation cannot be totally relied on to prevent the user from submitting invalid data. Any validation done within the client side must be replicated on the server, which is not open for manipulation by the user. We use client-side validation to improve the user experience. Because of this, the user does not need to wait for a server response. Implementing basic form validation At the most basic level of form validation, you will need to be able to prevent the user from submitting empty values. This recipe will provide the HTML and CSS code for a web form that will be used for recipes 1 through 8 of this article. Getting ready Using your favorite text editor or IDE, create a blank HTML page in an easily accessible location and save this file as recipe-1.html. Ensure that you have the latest version of jQuery downloaded to the same location as this HTML file. This HTML page will form the basis of most of this article, so remember to keep it after you have completed this recipe. How to do it… Learn how to implement basic form validation with jQuery by performing the following steps: Add the following HTML code to index.html. Be sure to change the source location of the JavaScript included for the jQuery library, pointing it to where the latest version of jQuery is downloaded on your computer. <!DOCTYPE html> <html > <head>    <title>Chapter 5 :: Recipe 1</title>    <link type="text/css" media="screen" rel="stylesheet" href="styles.css" />    <script src = "jquery.min.js"></script>    <script src = "validation.js"></script> </head> <body>    <form id="webForm" method="POST">       <div class="header">          <h1>Register</h1>       </div>       <div class="input-frame">          <label for="firstName">First Name:</label>          <input name="firstName" id="firstName" type="text"             class="required" />       </div>       <div class="input-frame">          <label for="lastName">Last Name:</label>          <input name="lastName" id="lastName" type="text"             class="required" />       </div>       <div class="input-frame">          <label for="email">Email:</label>          <input name="email" id="email" type="text"             class="required email" />       </div>       <div class="input-frame">          <label for="number">Telephone:</label>          <input name="number" id="number" type="text"             class="number" />       </div>       <div class="input-frame">          <label for="dob">Date of Birth:</label>          <input name="dob" id="dob" type="text"             class="required date"             placeholder="DD/MM/YYYY"/>       </div>       <div class="input-frame">          <label for="creditCard">Credit Card #:</label>          <input name="creditCard" id="creditCard"             type="text" class="required credit-card" />       </div>       <div class="input-frame">          <label for="password">Password:</label>          <input name="password" id="password"             type="password" class="required" />       </div>       <div class="input-frame">          <label for="confirmPassword">Confirm             Password:</label>             <input name="confirmPassword"                id="confirmPassword" type="password"                class="required" />       </div>       <div class="actions">          <button class="submit-btn">Submit</button>       </div>    </form> </body> </html> Create a CSS file named styles.css in the same directory and add the following CSS code to add style to our HTML page and form: @import url(http: //fonts.googleapis.com/css?family=Ubuntu); body {    background-color: #FFF;    font-family: 'Ubuntu', sans-serif; } form {    width: 500px;    padding: 20px;    background-color: #333;    border-radius: 5px;    margin: 10px auto auto auto;    color: #747474;    border: solid 2px #000; } form label {    font-size: 14px;    line-height: 30px;    width: 27%;    display: inline-block;    text-align: right; } .input-frame {    clear: both;    margin-bottom: 25px;    position: relative; } form input {    height: 30px;    width: 330px;    margin-left: 10px;    background-color: #191919;    border: solid 1px #404040;    padding-left: 10px;    color: #DB7400; } form input:hover {    background-color: #262626; } form input:focus {    border-color: #DB7400; } form .header {    margin: -20px -20px 25px -20px;    padding: 10px 10px 10px 20px;    position: relative;    background-color: #DB7400;    border-top-left-radius: 4px;    border-top-right-radius: 4px; } form .header h1 {    line-height: 50px;    margin: 0px;    padding: 0px;    color: #FFF;    font-weight: normal; } .actions {    text-align: right; } .submit-btn {    background-color: #DB7400;    border: solid 1px #000;    border-radius: 5px;    color: #FFF;    padding: 10px 20px 10px 20px;    text-decoration: none;    cursor: pointer; } .error input {    border-color: red; } .error-data {    color: red;    font-size: 11px;    position: absolute;    bottom: -15px;    left: 30%; } In addition to the jQuery library, the previous HTML page also uses another JavaScript file. Create a blank JavaScript file in the directory where the index.html file is saved. Save this file as validation.js and add the following JavaScript code: $(function(){    $('.submit-btn').click(function(event){       //Prevent form submission       event.preventDefault();       var inputs = $('input');       var isError = false;       //Remove old errors       $('.input-frame').removeClass('error');       $('.error-data').remove();       for (var i = 0; i < inputs.length; i++) {          var input = inputs[i];          if ($(input).hasClass('required') &&             !validateRequired($(input).val())) {             addErrorData($(input), "This is a required             field");             isError = true;          }         }       if (isError === false) {          //No errors, submit the form          $('#webForm').submit();       }    }); });   function validateRequired(value) {    if (value == "") return false;    return true; }   function addErrorData(element, error) {    element.parent().addClass("error");    element.after("<div class='error-data'>" + error + "</div>"); } Open index.html in a web browser and you should see a form similar to the following screenshot: If you click on the Submit button to submit an empty form, you will be presented with error messages under the required fields. How it works… Now, let us understand the steps performed previously in detail. HTML The HTML creates a web form with various fields that will take a range of data inputs, including text, date of birth, and credit card number. This page forms the basis for most of this article. Each of the input elements has been given different classes depending on what type of validation they require. For this recipe, our JavaScript will only look at the required class, which indicates a required field and therefore cannot be blank. Other classes have been added to the input fields, such as date and number, which will be used in the later recipes in this article. CSS Basic CSS has been added to create an attractive web form. The CSS code styles the input fields so they blend in with the form itself and adds a hover effect. The Google Web Font Ubuntu has also been used to improve the look of the form. jQuery The first part of the jQuery code is wrapped within $(function(){});, which will ensure the code is executed on page load. Inside this wrapper, we attach a click event handler to the form submit button, shown as follows: $(function(){     $('.submit-btn').click(function(event){         //Prevent form submission         event.preventDefault();             }); }); As we want to handle the form submission based on whether valid data has been provided, we use event.preventDefault(); to initially stop the form from submitting, allowing us to perform the validation first, shown as follows: var inputs = $('input'); var isError = false; After the preventDefault code, an inputs variable is declared to hold all the input elements within the page, using $('input') to select them. Additionally, we create an isError variable, setting it to false. This will be a flag to determine if our validation code has discovered an error within the form. These variable declarations are shown previously. Using the length of the inputs variable, we are able to loop through all of the inputs on the page. We create an input variable for each input that is iterated over, which can be used to perform actions on the current input element using jQuery. This is done with the following code: for (var i = 0; i < inputs.length; i++) { var input = inputs[i]; } After the input variable has been declared and assigned the current input, any previous error classes or data is removed from the element using the following code: $(input).parent().removeClass('error'); $(input).next('.error-data').remove(); The first line removes the error class from the input's parent (.input-frame), which adds the red border to the input element. The second line removes the error information that is displayed under the input if the validation check has determined that this input has invalid data. Next, jQuery's hasClass() function is used to determine if the current input element has the required class. If the current element does have this class, we need to perform the required validation to make sure this field contains data. We call the validateRequired() function within the if statement and pass through the value of the current input, shown as follows: if ($(input).hasClass('required') && !validateRequired($(input).val())) { addErrorData($(input), "This is a required field");    isError = true; } We call the validateRequired() function prepended with an exclamation mark to check to determine if this function's results are equal to false; therefore, if the current input has the required class and validateRequired() returns false, the value of the current input is invalid. If this is the case, we call the addErrorData() function inside the if statement with the current input and the error message, which will be displayed under the input. We also set the isError variable to true, so that later on in the code, we will know a validation error occurred. The JavaScript's for loop will repeat these steps for each of the selected input elements on the page. After the for loop has completed, we check if the isError flag is still set to false. If so, we use jQuery to manually submit the form, shown as follows: if (isError === false) {    //No errors, submit the form    $('#webForm').submit(); } Note that the operator === is used to compare the variable type of isError (that is, Boolean) as well as its value. At the bottom of the JavaScript file, we declare our two functions that have been called earlier in the script. The first function, validateRequired(), simply takes the input value and checks to see if it is blank or not. If the value is blank, the function returns false, meaning validation failed; otherwise, the function returns true. This can be coded as follows: function validateRequired(value) {     if (value == "") return false;     return true; } The second function used is the addErrorData() function, which takes the current input and an error message. It uses jQuery's addClass() function to add the error class to the input's parent, which will display the red border on the input element using CSS. It then uses jQuery's after() function to insert a division element into the DOM, which will display the specified error message under the current input field, shown as follows: function validateRequired(value) {    if (value == "") return false;    return true; } function addErrorData(element, error) {    element.parent().addClass("error");    element.after("<div class='error-data'>" + error + "</div>"); } There's more... This structure allows us to easily add additional validation to our web form. Because the JavaScript is iterating over all of the input fields in the form, we can easily check for additional classes, such as date, number, and credit-card, and call extra functions to provide the alternative validation. The other recipes in this article will look in detail at the additional validation types and add these functions to the current validation.js file. See also Implementing input character restrictions Adding number validation When collecting data from a user, there are many situations when you will want to only allow numbers in a form field. Examples of this could be telephone numbers, PIN codes, or ZIP codes, to name a few. This recipe will show you how to validate the telephone number field within the form we created in the previous recipe. Getting ready Ensure that you have completed the previous recipe and have the same files available. Open validation.js in your text editor or IDE of choice. How to do it… Add number validation to the form you created in the previous recipe by performing the following steps: Update validation.js to be as follows, adding the valdiateNumber() function with an additional hasClass('number') check inside the for loop: $(function(){    $('.submit-btn').click(function(event){       //Prevent form submission       event.preventDefault();       var inputs = $('input');       var isError = false;       //Remove old errors       $('.input-frame').removeClass('error');       $('.error-data').remove();       for (var i = 0; i < inputs.length; i++) {          var input = inputs[i];            if ($(input).hasClass('required') &&             !validateRequired($(input).val())) {                addErrorData($(input), "This is a required                   field");                isError = true;             } /* Code for this recipe */          if ($(input).hasClass('number') &&             !validateNumber($(input).val())) {                addErrorData($(input), "This field can only                   contain numbers");                isError = true;             } /* --- */         }       if (isError === false) {          //No errors, submit the form          $('#webForm').submit();       }    }); });   function validateRequired(value) {    if (value == "") return false;    return true; }   /* Code for this recipe */ function validateNumber(value) {    if (value != "") {       return !isNaN(parseInt(value, 10)) && isFinite(value);       //isFinite, in case letter is on the end    }    return true; } /* --- */ function addErrorData(element, error) {    element.parent().addClass("error");    element.after("<div class='error-data'>" + error + "</div>"); } Open index.html in a web browser, input something other than a valid integer into the telephone number field, and click on the Submit button. You will be presented with a form similar to the following screenshot: How it works… First, we add an additional if statement to the main for loop of validation.js to check to see if the current input field has the class number, as follows: if ($(input).hasClass('number') &&    !validateNumber($(input).val())) {    addErrorData($(input), "This field can only contain numbers");    isError = true; } If it does, this input value needs to be validated for a number. To do this, we call the validateNumber function inline within the if statement: function validateNumber(value) {    if (value != "") {       return !isNaN(parseInt(value, 10)) && isFinite(value);       //isFinite, in case letter is on the end    }    return true; } This function takes the value of the current input field as an argument. It first checks to see if the value is blank. If it is, we do not need to perform any validation here because this is handled by the validateRequired() function from the first recipe of this article. If there is a value to validate, a range of actions are performed on the return statement. First, the value is parsed as an integer and passed to the isNaN() function. The JavaScript isNaN() function simply checks to see if the provided value is NaN (Not a Number). In JavaScript, if you try to parse a value as an integer and that value is not actually an integer, you will get the NaN value. The first part of the return statement is to ensure that the provided value is a valid integer. However, this does not prevent the user from inputting invalid characters. If the user was to input 12345ABCD, the parseInt function would ignore ABCD and just parse 12345, and therefore the validation would pass. To prevent this situation, we also use the isFinite function, which returns false if provided with 12345ABCD. Adding credit card number validation Number validation could be enough validation for a credit card number; however, using regular expressions, it is possible to check for number combinations to match credit card numbers from Visa, MasterCard, American Express, and more. Getting ready Make sure that you have validation.js from the previous two recipes in this article open and ready for modification. How to do it… Use jQuery to provide form input validation for credit card numbers by performing the following step-by-step instructions: Update validation.js to add the credit card validation function and the additional class check on the input fields: $(function(){    $('.submit-btn').click(function(event){       //Prevent form submission       event.preventDefault();       var inputs = $('input');       var isError = false;       for (var i = 0; i < inputs.length; i++) {   // -- JavaScript from previous two recipes hidden                       if ($(input).hasClass('credit-card') &&             !validateCreditCard($(input).val())) {             addErrorData($(input), "Invalid credit card                number");             isError = true;          }         } // -- JavaScript from previous two recipes hidden    }); });   // -- JavaScript from previous two recipes hidden   function validateCreditCard(value) {    if (value != "") {       return /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9]) [0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}| (?:2131|1800|35d{3})d{11})$/.test(value);    }    return true; } // -- JavaScript from previous two recipes hidden } Open index.html and input an invalid credit card number. You will be presented with the following error information in the form: How it works… To add credit card validation, as with the previous two recipes, we added an additional check in the main for loop to look for the credit-card class on the input elements, as follows: if ($(input).hasClass('credit-card') &&    !validateCreditCard($(input).val())) {    addErrorData($(input), "Invalid credit card number");    isError = true; } The validateCreditCard function is also added, which uses a regular expression to validate the input value, as follows: function validateCreditCard(value) {    if (value != "") {       return /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-          9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-          9]{13}|3(?:0[0-5]|[68][0-9])[0-          9]{11}|(?:2131|1800|35d{3})d{11})$/.test(value);    }    return true; } The first part of this function determines if the provided value is blank. If it isn't, the function will perform further validation; otherwise, it will return true. Most credit card numbers start with a prefix, which allows us to add additional validation to the inputted value on top of numeric validation. The regular expression used in this function will allow for Visa, MasterCard, American Express, Diners Club, Discover, and JCB cards. See also Adding number validation
Read more
  • 0
  • 0
  • 2097

article-image-baritem-class-and-radoutlookbar-control
Packt
18 Feb 2014
6 min read
Save for later

The BarItem class and the RadOutlookBar control

Packt
18 Feb 2014
6 min read
(For more resources related to this topic, see here.) The next aspect of the system we want to review is the BarItem class. The design of this class is set up to be used by the RadOutlookBarItem and RadMenuItem classes. The reason for this setup was to match the properties of the Telerik item classes. The following is a screenshot of the class design: The main properties include Header, Position, and ReferId. The Header property is set up to match the Header property from the RadOutlookBarItem and RadmenuItem classes. The Position property orders the items on the system for proper display, and the ReferId property creates the structure of the view. The ReferId values are set up so that if the ReferId property is zero, this item becomes the header, otherwise the rest of the items become the items under that main item. Now that we've covered the new concepts within this article, let's start to work with the navigation containers for Telerik. The next sections of this article will cover the RadOutlookBar and RadMenu controls using the concepts from this section to load these controls based on the level of user access. RadOutlookBar The first control I will review in this article will be the RadOutlookBar control. This control is unique to the Telerik toolset. The standard Visual Studio control library does not contain a control like the RadOutlookBar control. The first example I will review will be to set the binding of the control's tabs using both a list of class objects from the object layer, and the database to populate the list of objects and authenticate the user. The first step will be to create a new window in the current WPF project; name this new window Chap5OutlookWindow.xaml. Once you have created the new window, you will need to add the RadOutlookBar control: RadOutlookBar: Name the outlook bar RadTestOutlook The final appearance of the window should be the following screenshot: Notice that the RadOutlookBar control is already loaded with the options. This is the fully functioning example, but gives you an idea for how the window should look once we've finished this section. RadOutlook with GenericList, DataBinding, and database security This is the first example of populating the RadOutlookBar with the menu links from the database. The concept we are demonstrating is that the menu links inside the RadOutlookBar control will be populated based on the user that is authenticated into the system. In this example, we will be using database security. This means that the database will store the username and password, and security link information for the RadOutlookBar control. Since we don't have a login form to gather the username and password, we will create the user information within the App.xaml.cs file instead. This will allow us to simulate the login process and authenticate the user in the system. This should not be done for a production application—this setup is for demonstration purposes only. Hard-coding a username and password is always a bad practice in a real-world application. The following screenshot shows how the code should look inside the App.xaml.cs file: Let's review the preceding code. The first step is to create an instance of the UserEntity class. The next step is to determine the type of security the system will be using to authenticate the user. The app.config file has a setting for the type of security as shown in the following line of code: <add key="SecurityType" value="DB"/> This key value is passed to the system, and used by the system to determine which type of security is used in the App.xaml.cs class. The value is read by the system; it sets an enum property from the UserEntity class called SecurityType. This enumeration is then evaluated to determine the security setup for the system. The next step is to set the UserName and UserChkPwd properties. Once these properties are set we can then call the Authenticate method to verify the user information against the database. The next step will be to set the CurrentUser property in the application request class. This object is passed to each window to persist base application information to each window. The final step will be to create an instance of the OutlookBarWindow class to open the window. Notice the code for the instance; we are passing the AppRequest object to the window using the instance method of the window. The following screenshot is the instance code: Now that the window code is set up, let's review the LoadRadOutlook method from the BaseWindow class. This method requires two values: the OutlookBar object to be loaded, and a generic list of BarItem objects. The BarItem class takes the information from the database and loads the RadOutlookBar control using BarItems to create the RadOutlookBarItem objects to load the RadOutlookBar control. The LoadRadOutlook method also creates a RadTreeView control of the options within each RadOutlookBarItem object. The database version then handles the gathering of the BarItem class and loading the RadOutlookBar control using a method called FetchMenuOptions. This method takes BarItems from the database query, and created a RadOutlookBar object with all the menu options for the current user. This method gathers the menu information based on the current username and generates a generic list of the BarItem classes. This list is used by the BaseWindow class to load the RadOutlookBar control. RadOutlookBar using generic list binding with XML security The next method for populating the RadOutlookBar control on the window will be to use a serialized XML to populate the generic list of objects to load the RadOutlookBar control. The XML file has the group information and pulls the BarItem objects based on the user's group information. The example we will be using has the group information hard-coded into the group list, but this is just an example. You should not hard-code the groups in a real-world application. Here is the method for gathering the menu items from the XML file: Notice that we first load the XDocument object, then deserialize the XDocument object to gather the list of BarItem objects. Once the full list is loaded, we use a Linq query to gather the items based on the user group for the current user. Now that we have that new list, we can populate the UserMenuItems property for use in the application. The application then calls the LoadOutlookBar method to generate the RadOutlookBar control again. Summary Thus in this article we learned what a RadOutlookBar control is and how it can be used with GenericList, DataBinding, database security and generic list binding with XML security. We also had a glance over the BarItem class and how the design of this class is set up to be used by the RadOutlookBarItem and RadMenuItem classes. Resources for Article: Further resources on this subject: WPF 4.5 Application and Windows [Article] Windows Presentation Foundation Project - Basics of Working [Article] Introduction to Web Experience Factory [Article]
Read more
  • 0
  • 0
  • 964
Banner background image

article-image-finishing-touches-and-publishing
Packt
18 Feb 2014
7 min read
Save for later

Finishing Touches and Publishing

Packt
18 Feb 2014
7 min read
(For more resources related to this topic, see here.) Publishing a Video Demo project Due to its very nature, a Video Demo project can only be published as an .mp4 video file. In the following exercise, you will return to the encoderVideo.cpvc project and explore the available publishing options: Open the encoderVideo.cpvc file under Chapter08. Make sure the file opens in Edit mode. If you are not in Edit mode, click on the Edit button at the lower-right corner of the screen. (If the Edit button is not displayed on the screen, it simply means that you already are in Edit mode.) When the file is open in Edit mode, take a look at the main toolbar at the top of the interface. Click on the Publish icon or navigate to File | Publish. The Publish Video Demo dialog opens. In the Publish Video Demo dialog, make sure the Name of the project is encoderVideo. Click on the … button and choose the publish folder of your exercises as the destination of the published video file. Open the Preset dropdown. Take some time to inspect the available presets. When done, choose the Video - Apple iPad preset. Make sure the Publish Video Demo dialog looks similar to what is shown in the following screenshot and click on the Publish button: Publishing a Video Demo project can be quite a lengthy process, so be patient. When the process is complete, a message asks you what to do next. Notice that one of the options enables you to upload your newly created video to YouTube directly. Click on the Close button to discard the message. Use Windows Explorer (Windows) or the Finder (Mac) to go to the publish folder of your exercises. Double-click on the encoderDemo.mp4 file to open the video in the default video player of your system. Remember that a Video Demo project can only be published as a video file. Also remember that the published .mp4 video file can only be experienced in a linear fashion and does not support any kind of interactivity. Publishing to Flash In the history of Captivate, publishing to Flash has always been the primary publishing option. Even though HTML5 publishing is a game changer, publishing to Flash is still an important capability of Captivate. Remember that this publishing format is currently the only one that supports every single feature, animation, and object of Captivate. In the following exercise, you will publish the Encoder Demonstration project in Flash using the default options: Return to the encoderDemo_800.cptx file under Chapter08. Click on the Publish icon situated right next to the Preview icon. Alternatively, you can also navigate to File | Publish. The Publish dialog box opens as shown in the following screenshot: Notice that the Publish dialog of a regular Captivate project contains far more options than its Publish Video Demo counterpart in .cpvc files. The Publish dialog box is divided into four main areas: The Publish Format area (1): This is where you choose the format in which you want to publish your projects. Basically, there are three options to choose from: SWF/HTML5, Media, and Print. The other options (E-Mail, FTP, and Adobe Connect) are actually suboptions of the SWF/HTML5, Media, and Print formats. The Output Format Options area (2): The content of this area depends on the format chosen in the Publish Format (1) area. The Project Information area (3): This area is a summary of the main project preferences and metadata. Clicking on the links of this area will bring you back to the corresponding preferences dialog boxes. The Advanced Options area (4): This area provides some additional advanced publishing options. You will now move on to the actual publication of the project in the Flash format. In the leftmost column of the Publish dialog, make sure the chosen format is SWF/HTML5. In the central area, change the Project Title to encoderDemo_800_flash. Click on the Browse… button situated just below the Folder field and choose to publish your movie in the publish folder of your exercises folder. Make sure the Publish to Folder checkbox is selected. Take a quick look at the remaining options, but leave them all at their current settings. Click on the Publish button at the bottom-right corner of the Publish dialog box. When Captivate has finished publishing the movie, an information box appears on the screen asking whether you want to view the output. Click on No to discard the information box and return to Captivate. You will now use the Finder (Mac) or the Windows Explorer (Windows) to take a look at the files Captivate has generated. Use the Finder (Mac) or the Windows Explorer (Windows) to browse to the publish folder of your exercises. Because you selected the Publish to Folder checkbox in the Publish dialog, Captivate has automatically created the encoderDemo_800_flash subfolder in the publish folder. Open the encoderDemo_800_flash subfolder to inspect its content.There should be five files stored in this location: encoderDemo_800_flash.swf: This is the main Flash file containing the compiled version of the .cptx project encoderDemo_800_flash.html: This file is an HTML page used to wrap the Flash file standard.js: This is a JavaScript file used to make the Flash player work well within the HTML page demo_en.flv: This is the video file used on slide 2 of the movie captivate.css: This file provides the necessary style rules to ensure there is proper formatting of the HTML page If you want to embed the compiled Captivate movie in an existing HTML page, only the .swf file (plus, in this case, the .flv video) is needed. The HTML editor (such as Adobe Dreamweaver) will recreate the necessary HTML, JavaScript, and CSS files. Captivate and DreamweaverAdobe Dreamweaver CC is the HTML editor of the Creative Cloud and the industry-leading solution for authoring professional web pages. Inserting a Captivate file in a Dreamweaver page is dead easy! First, move or copy the main Flash file (.swf) as well as the needed support files (in this case, the .flv video file), if any, somewhere in the root folder of the Dreamweaver site. When done, use the Files panel of Dreamweaver to drag and drop the main .swf file onto the HTML page. That's it! More information on Dreamweaver can be found at http://www.adobe.com/products/dreamweaver.html. You will now test the compiled project in a web browser. This is an important test as it closely recreates the conditions in which the students will experience the movie once uploaded on a web server. Double-click on the encoderDemo_800_flash.html file to open it in a web browser. Enjoy the final version of the demonstration you have created! Now that you have experienced the workflow of publishing the project to Flash with the default options, you will explore some additional publishing options. Using the Scalable HTML content option Thanks to Scalable HTML content option of Captivate, the eLearning content is automatically resized to fit the screen on which it is viewed. Let's experiment with this option hands on using the following steps: If needed, return to the encoderDemo_800.cptx file under Chapter08. Click on the Publish icon situated right next to the Preview icon. Alternatively, you can also navigate to File | Publish. In the leftmost column, make sure the chosen format is SWF/HTML5. In the central column, change the Project Title to encoderDemo_800_flashScalable. Click on the Browse… button situated just below the Folder field and ensure that the publish folder is still the publish folder of your exercises. Make sure the Publish to Folder checkbox is selected. In the Advanced Options section (lower-right corner of the Publish dialog), select the Scalable HTML content checkbox. Leave the remaining options at their current value and click on the Publish button at the bottom-right corner of the Publish dialog box. When Captivate has finished publishing the movie, an information box appears on the screen asking whether you want to view the output. Click on Yes to discard the information box and open the published movie in the default web browser. During the playback, use your mouse to resize your browser window and notice how the movie is resized and always fits the available space without being distorted. The Scalable HTML content option also works when the project is published in HTML5.
Read more
  • 0
  • 0
  • 1292

article-image-creating-shipping-module
Packt
17 Feb 2014
12 min read
Save for later

Creating a Shipping Module

Packt
17 Feb 2014
12 min read
(For more resources related to this topic, see here.) Shipping ordered products to customers is one of the key parts of the e-commerce flow. In most cases, a shop owner has a contract with a shipping handler where everyone has their own business rules. In a standard Magento, the following shipping handlers are supported: DHL FedEx UPS USPS If your handler is not on the list, have a look if there is a module available at Magento Connect. If not, you can configure a standard shipping method or you can create your own, which we will do in this article. Initializing module configurations In this recipe, we will create the necessary files for a shipping module, which we will extend with more features using the recipes of this article. Getting ready Open your code editor with the Magento project. Also, get access to the backend where we will check some things. How to do it... The following steps describe how we can create the configuration for a shipping module: Create the following folders: app/code/local/Packt/ app/code/local/Packt/Shipme/ app/code/local/Packt/Shipme/etc/ app/code/local/Packt/Shipme/Model/ app/code/local/Packt/Shipme/Model/Carrier Create the module file named Packt_Shipme.xml in the folder app/etc/modules with the following content: <?xml version="1.0"?> <config> <modules> <Packt_Shipme> <active>true</active> <codePool>local</codePool> <depends> <Mage_Shipping /> </depends> </Packt_Shipme> </modules> </config> Create a config.xml file in the folder app/code/local/Packt/Shipme/etc/ with the following content: <?xml version="1.0" encoding="UTF-8"?> <config> <modules> <Packt_Shipme> <version>0.0.1</version> </Packt_Shipme> </modules> <global> <models> <shipme> <class>Packt_Shipme_Model</class> </shipme> </models> </global> <default> <carriers> <shipme> <active>1</active> <model>shipme/carrier_shipme</model> <title>Shipme shipping</title> <express_enabled>1</express_enabled> <express_title>Express delivery</express_title> <express_price>4</express_price> <business_enabled>1</business_enabled> <business_title>Business delivery</business_title> <business_price>5</business_price> </shipme> </carriers> </default> </config> Clear the cache and navigate in the backend to System | Configuration | Advanced Disable Modules Output. Observe that the Packt_Shipme module is on the list. At this point, the module is initialized and working. Now, we have to create a system.xml file where we will put the configuration parameters for our shipping module. Create the file app/code/local/Packt/Shipme/etc/system.xml. In this file, we will create the configuration parameters for our shipping module. When you paste the following code in the file, you will create an extra group in the shipping method's configuration. In this group, we can set the settings for the new shipping method: <?xml version="1.0" encoding="UTF-8"?> <config> <sections> <carriers> <groups> <shipme translate="label" module="shipping"> <label>Shipme</label> <sort_order>15</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> <fields> <!-- Define configuration fields below --> <active translate="label"> <label>Enabled</label> <frontend_type>select</frontend_type> <source_model>adminhtml/ system_config_source_yesno</source_model> <sort_order>10</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </active> <title translate="label"> <label>Title</label> <frontend_type>text</frontend_type> <sort_order>20</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </title> </fields> </shipme> </groups> </carriers> </sections> </config> Clear the cache and navigate in the backend to the shipping method configuration page. To do that, navigate to System | Configuration | Sales | Shipping methods. You will see that an extra group is added as shown in the following screenshot: You will see that there is a new shipping method called Shipme. We will extend this configuration with some values. Add the following code under the <fields> tag of the module: <active translate="label"> <label>Enabled</label> <frontend_type>select</frontend_type> <source_model>adminhtml/system_config_source_yesno</source_ model> <sort_order>10</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </active> <title translate="label"> <label>Title</label> <frontend_type>text</frontend_type> <sort_order>20</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </title> <express_enabled translate="label"> <label>Enable express</label> <frontend_type>select</frontend_type> <source_model>adminhtml/system_config_source_yesno</source_ model> <sort_order>30</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </express_enabled> <express_title translate="label"> <label>Title express</label> <frontend_type>text</frontend_type> <sort_order>40</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </express_title> <express_price translate="label"> <label>Price express</label> <frontend_type>text</frontend_type> <sort_order>50</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </express_price> <business_enabled translate="label"> <label>Enable business</label> <frontend_type>select</frontend_type> <source_model>adminhtml/system_config_source_yesno</source_ model> <sort_order>60</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </business_enabled> <business_title translate="label"> <label>Title business</label> <frontend_type>text</frontend_type> <sort_order>70</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </business_title> <business_price translate="label"> <label>Price business</label> <frontend_type>text</frontend_type> <sort_order>80</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </business_price> Clear the cache and reload the backend. You will now see the other configurations under the Shipme – Express shipping method as shown in the following screenshot: How it works... The first thing we have done is to create the necessary files to initialize the module. The following files are required to initialize a module: app/etc/modules/Packt_Shipme.xml app/code/local/Packt/Shipme/etc/config.xml In the first file, we will activate the module with the <active> tag. The <codePool> tag describes that the module is located in the local code pool, which represents the folder app/code/local/. In this file, there is also the <depends> tag. First this will check if the Mage_Shipping module is installed or not. If not, Magento will throw an exception. If the module is available, the dependency will load this module after the Mage_Shipping module. This makes it possible to rewrite some values from the Mage_Shipping module. In the second file, config.xml, we configured all the stuff that we will need in this module. These are the following things: The version number (0.0.1) The models Some default values for the configuration values The last thing we did was create a system.xml file so that we can create a custom configuration for the shipping module. The configuration in the system.xml file adds some extra values to the shipping method configuration, which is available in the backend under the menu System | Configuration | Sales | Shipping methods. In this module, we created a new shipping handler called Shipme. Within this handler, you can configure two shipping options: express and business. In the system.xml file, we created the fields to configure the visibility, name, and price of the options. See also In this recipe, we used the system.xml file of the module to create the configuration values. Writing an adapter model A new shipping module is initialized in the previous recipe. What we did in the previous recipe was a preparation to continue with the business part we will see in this recipe. We will add a model with the business logic for the shipping method. The model is called an adapter class because Magento requires an adapter class for each shipping method. This class will extend the Mage_Shipping_Model_Carrier_Abstract class. This class will be used for the following things: Make the shipping method available Calculate the shipping costs Set the title in the frontend of the shipping methods How to do it... Perform the following steps to create the adapter class for the shipping method: Create the folder app/code/local/Packt/Shipme/Model/Carrier if it doesn't already exist. In this folder, create a file named Shipme.php and add the following content to it: <?php class Packt_Shipme_Model_Carrier_Shipme extends Mage_Shipping_Model_Carrier_Abstract implements Mage_Shipping_Model_Carrier_Interface { protected $_code = 'shipme'; public function collectRates (Mage_Shipping_Model_Rate_Request $request) { $result = Mage::getModel('shipping/rate_result'); //Check if express method is enabled if ($this->getConfigData('express_enabled')) { $method = Mage::getModel ('shipping/rate_result_method'); $method->setCarrier($this->_code); $method->setCarrierTitle ($this->getConfigData('title')); $method->setMethod('express'); $method->setMethodTitle ($this->getConfigData('express_title')); $method->setCost ($this->getConfigData('express_price')); $method->setPrice ($this->getConfigData('express_price')); $result->append($method); } //Check if business method is enabled if ($this->getConfigData('business_enabled')) { $method = Mage::getModel ('shipping/rate_result_method'); $method->setCarrier($this->_code); $method->setCarrierTitle ($this->getConfigData('title')); $method->setMethod('business'); $method->setMethodTitle ($this->getConfigData('business_title')); $method->setCost ($this->getConfigData('business_price')); $method->setPrice ($this->getConfigData('business_price')); $result->append($method); } return $result; } public function isActive() { $active = $this->getConfigData('active'); return $active==1 || $active=='true'; } public function getAllowedMethods() { return array('shipme'=>$this->getConfigData('name')); } } Save the file and clear the cache; your adapter model has now created. How it works... The previously created class handles all the business logic that is needed for the shipping method. Because this adapter class is an extension of the Mage_Shipping_Model_Carrier_Abstract class, we can overwrite some methods to customize the business logic of the standard. The first method we overwrite is the isAvailable() function. In this function, we have to return true or false to say that the module is active. In our code, we will activate the module based on the system configuration field active. The second method is the collectRates() function. This function is used to set the right parameters for every shipping method. For every shipping method, we can set the title and price. The class implements the interface Mage_Shipping_Model_Carrier_Interface. In this interface, two functions are declared: the isTrackingAvailable() and getAllowedMethods() functions. We created the function getAllowedMethods() in the adapter class. The isTrackingAvailable() function is declared in the parent class Mage_Shipping_Model_Carrier_Abstract. We configured two options under the Shipme shipping method. These options are called Express delivery and Business delivery. We will check if they are enabled in the configuration and set the configured title and price for each option. The last thing to do is return the right values. We have to return an instance of the class Mage_Shipping_Model_Rate_Result. We created an empty instance of the class, where we will append the methods to when they are available. To add a method, we have to use the function append($method). This function requires an instance of the class Mage_Shipping_Model_Rate_Result_Method that we created in the two if statements.
Read more
  • 0
  • 0
  • 1710

article-image-creating-attention-grabbing-pricing-tables
Packt
17 Feb 2014
6 min read
Save for later

Creating attention-grabbing pricing tables

Packt
17 Feb 2014
6 min read
(For more resources related to this topic, see here.) Let's revisit the mockup of how our client would like the pricing tables to look on desktop-sized screens: Let's see how close we can get to the desired result, and what we can work out for other viewport sizes. Setting up the variables, files, and markup As shown in the preceding screenshot, there are a few tables in this design. We can begin by adjusting a few fundamental variables for all tables. These are found in _variables.less. Search for the tables section and adjust the variables for background, accented rows, and borders as desired. I've made these adjustments as shown in the following lines of code: // Tables // ------------------------- ... @table-bg: transparent; // overall background-color @table-bg-accent: hsla(0,0,1%,.1); // for striping @table-bg-hover: hsla(0,0,1%,.2); @table-bg-active: @table-bg-hover; @table-border-color: #ccc; // table and cell border Save the file, compile it to CSS, and refresh to see the result as shown in the following screenshot: That's a start. Now we need to write the more specific styles. The _page-contents.less file is now growing long, and the task before us is extensive and highly focused on table styles. To carry the custom styles, let's create a new LESS file for these pricing tables: Create _pricing-tables.less in the main less folder. Import it into __main.less just after _page-contents.less as shown in the following line: @import "_pricing-tables.less"; Open _pricing-tables.less in your editor and begin writing your new styles. But before we begin writing styles, let's review the markup that we'll be working with. We have the following special classes already provided in the markup on the parent element of each respective table:   package package-basic package package-premium package package-pro   Thus, for the first table, you'll see the following markup on its parent div: <div class="package package-basic col-lg-4"> <table class="table table-striped"> ... Similarly, we'll use package package-premium and package package-pro for the second and third table, respectively. These parent containers obviously also provide basic layout instructions using the col-md-4 class to set up a three-column layout in medium viewports. Next, we will observe the markup for each table. We see that the basic table and table-striped classes have been applied: <table class="table table-striped"> The table uses the <thead> element for its top-most block. Within this, there is <th> spanning two columns, with an <h2> heading for the package name and <div class="price"> to markup the dollar amount: <thead><tr><th colspan="2"><h2>Basic Plan</h2><div class="price">$19</div></th></tr></thead> Next is the tfoot tag with the Sign up Now! button: <tfoot><tr><td colspan="2"><a href="#" class="btn">Sign upnow!</a></td></tr></tfoot> Then is the tbody tag with the list of features laid out in a straightforward manner in rows with two columns: <tbody><tr><td>Feature</td><td>Name</td></tr><tr><td>Feature</td><td>Name</td></tr><tr><td>Feature</td><td>Name</td></tr><tr><td>Feature</td><td>Name</td></tr><tr><td>Feature</td><td>Name</td></tr></tbody> And finally, of course, the closing tags for the table and parent div tags: </table></div><!-- /.package .package-basic --> Each table repeats this basic structure. This gives us what we need to start work! Beautifying the table head To beautify the thead element of all of our tables, we'll do the following: Align the text at the center Add a background color—for now, add a gray color that is approximately a midtone similar to the colors we'll apply to the final version Turn the font color white Convert the h2 heading to uppercase Increase the size of the price table Add the necessary padding all around the tables We can apply many of these touches with the following lines of code. We'll specify the #signup section as the context for these special table styles: #signup {table {border: 1px solid @table-border-color;thead th {text-align: center;background-color: @gray-light;color: #fff;padding-top: 12px;padding-bottom: 32px;h2 {text-transform: uppercase;}}}} In short, we've accomplished everything except increasing the size of the price tables. We can get started on this by adding the following lines of code, which are still nested within our #signup table selector: .price { font-size: 7em; line-height: 1;} This yields the following result: This is close to our desired result, but we need to decrease the size of the dollar sign. To give ourselves control over that character, let's go to the markup and wrap a span tag around it: <em class="price"><span>$</span>19</em> Remember to do the same for the other two tables. With this new bit of markup in place, we can nest this within our styles for .price: .price {...span {font-size: .5em;vertical-align: super;} These lines reduce the dollar sign to half its size and align it at the top. Now to recenter the result, we need to add a bit of negative margin to the parent .price selector: .price {margin-left: -0.25em;... The following screenshot shows the result: Styling the table body and foot By continuing to focus on the styles that apply to all three pricing tables, let's make the following adjustments: Add left and right padding to the list of features Stretch the button to full width Increase the button size We can accomplish this by adding the following rules: #signup {table {...tbody {td {padding-left: 16px;padding-right: 16px;}}a.btn {.btn-lg;display: block;width: 100%;background-color: @gray-light;color: #fff;}}} Save the file, compile it to CSS, and refresh the browser. You should see the following result: We're now ready to add styles to differentiate our three packages.
Read more
  • 0
  • 0
  • 1800
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 €14.99/month. Cancel anytime
article-image-how-expand-your-knowledge
Packt
17 Feb 2014
11 min read
Save for later

How to Expand your Knowledge

Packt
17 Feb 2014
11 min read
(For more resources related to this topic, see here.) One of the most frequently asked questions on help forums probably is, "How can I learn Google Apps Script?" The answer is almost always the same: learn JavaScript and follow the numerous tutorials available on the Internet. No doubt, it is one of the possible ways to learn but it is also one of the most difficult ways. I shall express my opinion on that subject at the end of this article, but let us first summarize what we really need to be able to use Google Apps Script efficiently. The first and most important thing we must have is a clear idea of what we want to achieve. This seems a bit silly because we think, "Oh well, of course I know what I want; I just don't know how to do it!" As a matter of fact, this is often not the case. Let us have an example: a colleague asked me recently how he could count the time he was spending at school for meetings and other administrative tasks, not taking into account his hours as a teacher. This was supposed to be a simple problem as everyone in our school has a personal calendar in which all the events that we are invited to are recorded. So, he began to search for a way to collect every possible event from his calendar to a spreadsheet and from there—since he can definitely use a spreadsheet—he intended to do some data filtering to get the result he wanted. I told him to have a look at the Google Apps Script documentation and see what tools he had, to pick up data from calendars and import them into a spreadsheet. A few days later, he came back to me complaining that he didn't find any appropriate methods to do what he needs to. And, in a way, he was right; nowhere is such a workflow explained and it is actually not surprising. One can't imagine compiling all the possible workflows into a single help resource; there are definitely too many different use cases, each of them needing a particular approach. We had a discussion where I told him to think about his research as a series of simple and accurate parts and steps before trying to get the whole process in one stroke. The following is what he told me another few days later: "I knew nothing about this macro language, so I discovered that it is based on JavaScript with the addition of Google's own services that use a similar syntax and that the whole thing is composed of functions calling each other and having parameters. Then, I examined the calendar service and saw that it needs so-called date objects to choose a start and end date. Date object methods are pretty well explained on Mozilla's page, so once I got that I had an array of events, I thought what the heck is an array of objects? You gave me the link to this w3schools site, so I took a look at their definition; that was enough for me to go further and discover that I could use a loop to handle each event separately. Google documentation shows all the methods to get events details; that part was easy and now I have all my calendar events with dates, hours, description, title. All of it! I tell you." I'm not going to transcribe all of our conversation—it finally took a couple of hours—but towards the end, he was describing the process so well that the actual writing of his script was almost just a formality. With the help of the Content assist (autocomplete) feature of the script editor and a couple of browser tabs left open on JavaScript and Google documentation, he managed to write his script in one day. Of course, the script was not perfect and by no way optimized his speed or gave  nice-looking results, but it worked and he had the data he was looking for. At that point, he could post his script on a help forum if something went wrong or try to improve another version if he's a perfectionist, but that depends only on his will to go further or not. I would simply say one thing: you will learn what you need. If you don't need it, don't try to learn it as you will forget it faster than you learned it. If you do, then be prepared to need something else right after; it is an endless journey! JavaScript versus Google Apps Script The following is stated on the overview of Google Apps Script documentation page: Google Apps Script is a scripting language based on JavaScript that lets you do new and cool things with Google Apps like Docs, Sheets, and Forms. They should use a bigger typeface to make it more visible! The keyword here is based on JavaScript because it does indeed use most of the JavaScript Version 1.6 (with some portions of Version 1.7 and Version 1.8) and its general syntax. But, it has so many other methods that knowing only JavaScript is clearly not sufficient to use it adequately. I would even say that you can learn it step-by-step when you need it, looking for information on a specific item each time you use a new type of object. The following is the code that was used to get the integer part of the result that uses the getTime method: function myAgeInHours(){  var myBirthDate = new Date('1958/02/19 02:00:00').getTime();  myBirthDate = parseInt(myBirthDate/3600000, 10);  var today = parseInt(new Date().getTime()/3600000, 10);  return today-myBirthDate;} We looked at the documentation about the Date object to find the getTime() method and then found parseInt to get the integer part of the result. Well, I'm convinced that this approach is more efficient than spending hours on a site or in a book that shows all JavaScript information from A to Z. We have the opportunity to have powerful search engines in our browsers, so let's use them; they always find the answer for us in less time than it takes to write the question. Concerning methods specific to Google Apps Script, I think the approach should be different. The Google API documentation is pretty well organized and is full of code examples that clearly show us how to use almost every single method. If we start a project in a spreadsheet, it is a good idea to carefully read the section about spreadsheets (https://developers.google.com/apps-script/reference/spreadsheet) at least once and just check if what it says makes any sense. For example, in the Sheet class, I found this description: Returns the range with the top left cell at the given coordinates, and with the given number of rows. The following screenshot displays the same description: If I understand what range and co-ordinates are, then I probably know enough to be able to use that method (getRange(row, column, numRows) or a similar one. You want me to tell you the truth? I didn't know we could get a range this way by simply defining the top-left cell and just the number of rows (only three parameters). I always use the next one in the list, which is shown as follows: The description says: Returns the range with the top left cell at the given coordinates with the given number of rows and columns. So after all this time I spent on dozens of spreadsheet scripts, there still are methods that I can't even imagine exist! That's actually a nice confirmation of what I was suggesting: one doesn't need to know everything to be able to use it but it's always a good idea to read the docs from time to time. Infinite resources JavaScript is a very popular language; there are thousands of websites that show us examples and explain methods and functions. We must add all the forums and Q&A sites that return many results when we search something on Google to these websites (or any other search engine), and that is actually an unforeseen difficulty. It happens quite often that we find false information or code snippets that simply don't work, either because they have typos in them or they are so badly written that they work only in a very specific and peculiar situation. My personal solution is to use only a couple of websites and perform a search on their search engine, avoiding all the sources I'm not sure of. Maybe I miss something at times, but at least the information I get is trustworthy. Last but certainly not least, the help forum recommended by the Google Apps Script team, http://stackoverflow.com/questions/tagged/google-apps-script (with the google-apps-script tag), is certainly the best resource that is available. With more than 5000 questions (as of January, 2014), the help forum probably has threads about every possible use case and an important part of it has answers as well. There are of course other interesting tags: JavaScript, Google docs, Google spreadsheets, and a few even more specific ones. I have rarely seen really bad answers—although it does happen sometimes—simply because so many people read these posts that they generally flag or comment answers that show wrong information. There are also people from Google that regularly keep an eye on it and clarify any ambiguous response. Being a newbie is, by definition, temporary When I began to use Google spreadsheets and scripts, I found the Google Group Help forum (which does not exist anymore) an invaluable source of information and help, so I asked dozens of questions—some of them very basic and naive—and always got answers. After a while, since I was spending hours on this forum reading about every post I found, I began to answer too. I was so proud of being able to answer a question! It was almost like passing an examination; I knew that one of the experts there was going to read what I wrote and evaluate my knowledge; quite stressful but also satisfying when you don't fail! So after a couple of months I gained my first level point (on the Google Group forum, there are no reputation points but levels, starting from 1 for new arriving members up to TC(Top Contributors), whose level is unknown but is generally more than 15 or 20; anyway, that's not important). That little story is just a way to encourage any beginner to spend some time on this forum and consider every question as a challenge and try to answer it. Of course, there is no need to publish your answer every time as there are chances that you may get it all wrong, but just use this as an exercise that will give you more and more expertise. From time to time, you'll be able to be the first or best answerer and gain a few reputation points; consider it as a game, just a funny game where all you can finally win is knowledge and all you can lose is your newbie status—not a bad deal after all! Try to find your own best learning method I'm certainly not pretending that I know the best learning method for anyone. All the tips I presented in the previous section did work for me—and for a few other people I know—but there is no magic formula that would suit everyone. I know that each of us has a different background and follows a different path, but I wanted to say loud and clear that you don't need to have to be a graduate in IT to begin with Google Apps Script nor do you have to spend hours learning rules and conventions. Practice will make it easier everyday and motivation will give you enough energy to complete your projects, from simple ones to more ambiguous ones. Summary This article has given an overview of the many resources available to improve your learning experience. There are certainly more that I don't know of but as I already mentioned a few times before, we have powerful search engines in our browsers to help us. We also have to keep in mind that Google Apps Script will probably be different as compared to what it will be in a couple of years. Resources for Article: Further resources on this subject: Google Apps: Surfing the Web [Article] Developing apps with the Google Speech APIs [Article] Data Modeling and Scalability in Google App [Article]
Read more
  • 0
  • 0
  • 1310

Packt
14 Feb 2014
6 min read
Save for later

CreateJS – Performing Animation and Transforming Function

Packt
14 Feb 2014
6 min read
(For more resources related to this topic, see here.) Creating animations with CreateJS As you may already know, creating animations in web browsers during web development is a difficult job because you have to write code that has to work in all browsers; this is called browser compatibility. The good news is that CreateJS provides modules to write and develop animations in web browsers without thinking about browser compatibility. CreateJS modules can do this job very well and all you need to do is work with CreateJS API. Understanding TweenJS TweenJS is one of the modules of CreateJS that helps you develop animations in web browsers. We will now introduce TweenJS. The TweenJS JavaScript library provides a simple but powerful tweening interface. It supports tweening of both numeric object properties and CSS style properties, and allows you to chain tweens and actions together to create complex sequences.—TweenJS API Documentation What is tweening? Let us understand precisely what tweening means: Inbetweening or tweening is the process of generating intermediate frames between two images to give the appearance that the first image evolves smoothly into the second image.—Wikipedia The same as other CreateJS subsets, TweenJS contains many functions and methods; however, we are going to work with and create examples for specific basic methods, based on which you can read the rest of the documentation of TweenJS to create more complex animations. Understanding API and methods of TweenJS In order to create animations in TweenJS, you don't have to work with a lot of methods. There are a few functions that help you to create animations. Following are all the methods with a brief description: get: It returns a new tween instance. to: It queues a tween from the current values to the target properties. set: It queues an action to set the specified properties on the specified target. wait: It queues a wait (essentially an empty tween). call: It queues an action to call the specified function. play: It queues an action to play (un-pause) the specified tween. pause: It queues an action to pause the specified tween. The following is an example of using the Tweening API: var tween = createjs.Tween.get(myTarget).to({x:300},400). set({label:"hello!"}).wait(500).to({alpha:0,visible:false},1000). call(onComplete); The previous example will create a tween, which: Tweens the target to an x value of 300 with duration 400ms and sets its label to hello!. Waits 500ms. Tweens the target's alpha property to 0with duration 1s and sets the visible property to false. Finally, calls the onComplete function. Creating a simple animation Now, it's time to create our simplest animation with TweenJS. It is a simple but powerful API, which gives you the ability to develop animations with method chaining. Scenario The animation has a red ball that comes from the top of the Canvas element and then drops down. In the preceding screenshot, you can see all the steps of our simple animation; consequently, you can predict what we need to do to prepare this animation. In our animation,we are going to use two methods: get and to. The following is the complete source code for our animation: var canvas = document.getElementById("canvas"); var stage = new createjs.Stage(canvas); var ball = new createjs.Shape(); ball.graphics.beginFill("#FF0000").drawCircle(0, 0, 50); ball.x = 200; ball.y = -50; var tween = createjs.Tween.get(ball) to({ y: 300 }, 1500, createjs.Ease.bounceOut); stage.addChild(ball); createjs.Ticker.addEventListener("tick", stage); In the second and third line of the JavaScript code snippet, two variables are declared, namely; the canvas and stage objects. In the next line, the ball variable is declared, which contains our shape object. In the following line, we drew a red circle with the drawCircle method. Then, in order to set the coordinates of our shape object outside the viewport, we set the x axis to -50 px. After this, we created a tween variable, which holds the Tween object; then, using the TweenJS method chaining, the to method is called with duration of 1500 ms and the y property set to 300 px. The third parameter of the to method represents the ease function of tween, which we set to bounceOut in this example. In the following lines, the ball variable is added to Stage and the tick event is added to the Ticker class to keep Stage updated while the animation is playing. You can also find the Canvas element in line 30, using which all animations and shapes are rendered in this element. Transforming shapes CreateJS provides some functions to transform shapes easily on Stage. Each DisplayObject has a setTransform method that allows the transforming of a DisplayObject (like a circle). The following shortcut method is used to quickly set the transform properties on the display object. All its parameters are optional. Omitted parameters will have the default value set. setTransform([x=0] [y=0] [scaleX=1] [scaleY=1] [rotation=0] [skewX=0] [skewY=0] [regX=0] [regY=0]) Furthermore, you can change all the properties via DisplayObject directly (like scaleY and scaleX) as shown in the following example: displayObject.setTransform(100, 100, 2, 2); An example of Transforming function As an instance of using the shape transforming feature with CreateJS, we are going to extend our previous example: var angle = 0; window.ball; var canvas = document.getElementById("canvas"); var stage = new createjs.Stage(canvas); ball = new createjs.Shape(); ball.graphics.beginFill("#FF0000").drawCircle(0, 0, 50); ball.x = 200; ball.y = 300; stage.addChild(ball); function tick(event) { angle += 0.025; var scale = Math.cos(angle); ball.setTransform(ball.x, ball.y, scale, scale); stage.update(event); } createjs.Ticker.addEventListener("tick", tick); In this example, we have a red circle, similar to the previous example of tweening. We set the coordinates of the circle to 200 and 300 and added the circle to the stage object. In the next line, we have a tick function that transforms the shape of the circle. Inside this function, we have an angle variable that increases with each call. We then set the ballX and ballY coordinate to the cosine of the angle variable. The transforming done is similar to the following screenshot: This is a basic example of transforming shapes in CreateJS, but obviously, you can develop and create better transforming by playing with a shape's properties and values. Summary In this article, we covered how to use animation and transform objects on the page using CreateJS. Resources for Article: Further resources on this subject: Introducing a feature of IntroJs [Article] So, what is Node.js? [Article] So, what is Ext JS? [Article]
Read more
  • 0
  • 0
  • 1418

article-image-adding-health-checks
Packt
14 Feb 2014
3 min read
Save for later

Adding health checks

Packt
14 Feb 2014
3 min read
(For more resources related to this topic, see here.) A health check is a runtime test for our application. We are going to create a health check that tests the creation of new contacts using the Jersey client. The health check results are accessible through the admin port of our application, which by default is 8081. How to do it… To add a health check perform the following steps: Create a new package called com.dwbook.phonebook.health and a class named NewContactHealthCheck in it: import javax.ws.rs.core.MediaType; import com.codahale.metrics.health.HealthCheck; import com.dwbook.phonebook.representations.Contact; import com.sun.jersey.api.client.*; public class NewContactHealthCheck extends HealthCheck { private final Client client; public NewContactHealthCheck(Client client) { super(); this.client = client; } @Override protected Result check() throws Exception { WebResource contactResource = client .resource("http://localhost:8080/contact"); ClientResponse response = contactResource.type( MediaType.APPLICATION_JSON).post( ClientResponse.class, new Contact(0, "Health Check First Name", "Health Check Last Name", "00000000")); if (response.getStatus() == 201) { return Result.healthy(); } else { return Result.unhealthy("New Contact cannot be created!"); } } } Register the health check with the Dropwizard environment by using the HealthCheckRegistry#register() method within the #run() method of the App class. You will first need to import com.dwbook.phonebook.health.NewContactHealthCheck. The HealthCheckRegistry can be accessed using the Environment#healthChecks() method: // Add health checks e.healthChecks().register ("New Contact health check", new NewContactHealthCheck(client)); After building and starting your application, navigate with your browser to http://localhost:8081/healthcheck: The results of the defined health checks are presented in the JSON format. In case the custom health check we just created or any other health check fails, it will be flagged as "healthy": false, letting you know that your application faces runtime problems. How it works… We used exactly the same code used by our client class in order to create a health check; that is, a runtime test that confirms that the new contacts can be created by performing HTTP POST requests to the appropriate endpoint of the ContactResource class. This health check gives us the required confidence that our web service is functional. All we need for the creation of a health check is a class that extends HealthCheck and implements the #check() method. In the class's constructor, we call the parent class's constructor specifying the name of our check—the one that will be used to identify our health check. In the #check() method, we literally implement a check. We check that everything is as it should be. If so, we return Result.healthy(), else we return Result.unhealthy(), indicating that something is going wrong. Summary This article showed what a health check is and demonstrated how to add a health check. The health check we created tested the creation of new contacts using the Jersey client. Resources for Article: Further resources on this subject: RESTful Web Services – Server-Sent Events (SSE) [Article] Connecting to a web service (Should know) [Article] Web Services and Forms [Article]
Read more
  • 0
  • 0
  • 2983

article-image-using-phalcon-models-views-and-controllers
Packt
20 Jan 2014
3 min read
Save for later

Using Phalcon Models, Views, and Controllers

Packt
20 Jan 2014
3 min read
(For more resources related to this topic, see here.) Creating CRUD scaffolding CRUD stands for create, read, update, and delete, which are the four basic functions our application should do with our blog post records. Phalcon web tools will also help us to get these built. Click on the Scaffold tab on the web tools page and you will see a page as shown in the following screenshot: Select posts from the Table name list and volt from the Template engine list, and check Force this time, because we are going to force our new files to overwrite the old model and controller files that we just generated. Click on the Generate button and some magic should happen. Browse to http://localhost/phalconBlog/posts and you will see a page like the following screenshot: We finally have some functionality we can use. We have no posts, but we can create some. Click on the Create posts link and you will see a page similar to the one we were just at. The form will look nearly the same, but it will have a Create posts heading. Fill out the Title, Body, and Excerpt fields and click on the Save button. The form will post, and you will get a message stating that the post was created successfully. This will take you back to the post's index page. Now you should be able to search for and find the post you just created. If you forgot what you posted, you can click on Search without entering anything in the fields, and you should see a page like the following screenshot: This is not a very pretty or user-friendly blog application. But it got us started, and that's all we need. The next time we start a Phalcon project, it should only take a few minutes to go through these steps. Now we will look over our generated code, and as we do, modify it to make it more blog-like. Summary In this article, we worked on the model, view, and controller for the posts in our blog. To do this, we used Phalcon web tools to generate our CRUD scaffolding for us. Then, we modified this generated code so it would do what we need it to do. We can now add posts. We also learned about the Volt template engine. Resources for Article: Further resources on this subject: Using An Object Oriented Approach for Implementing PHP Classes to Interact with Oracle [Article] FuelPHP [Article] Installing PHP-Nuke [Article]
Read more
  • 0
  • 0
  • 1584
article-image-search-using-beautiful-soup
Packt
20 Jan 2014
6 min read
Save for later

Search Using Beautiful Soup

Packt
20 Jan 2014
6 min read
(For more resources related to this topic, see here.) Searching with find_all() The find() method was used to find the first result within a particular search criteria that we applied on a BeautifulSoup object. As the name implies, find_all() will give us all the items matching the search criteria we defined. The different filters that we see in find() can be used in the find_all() method. In fact, these filters can be used in any searching methods, such as find_parents() and find_siblings(). Let us consider an example of using find_all(). Finding all tertiary consumers We saw how to find the first and second primary consumer. If we need to find all the tertiary consumers, we can't use find(). In this case, find_all() will become handy. all_tertiaryconsumers = soup.find_all(class_="tertiaryconsumerslist") The preceding code line finds all the tags with the = "tertiaryconsumerlist" class. If given a type check on this variable, we can see that it is nothing but a list of tag objects as follows: print(type(all_tertiaryconsumers)) #output <class 'list'> We can iterate through this list to display all tertiary consumer names by using the following code: for tertiaryconsumer in all_tertiaryconsumers: print(tertiaryconsumer.div.string) #output lion tiger Understanding parameters used with find_all() Like find(), the find_all() method also has a similar set of parameters with an extra parameter, limit, as shown in the following code line: find_all(name,attrs,recursive,text,limit,**kwargs) The limit parameter is used to specify a limit to the number of results that we get. For example, from the e-mail ID sample we saw, we can use find_all() to get all the e-mail IDs. Refer to the following code: email_ids = soup.find_all(text=emailid_regexp) print(email_ids) #output [u'[email protected]',u'[email protected]',u'[email protected]'] Here, if we pass limit, it will limit the result set to the limit we impose, as shown in the following example: email_ids_limited = soup.find_all(text=emailid_regexp,limit=2) print(email_ids_limited) #output [u'[email protected]',u'[email protected]'] From the output, we can see that the result is limited to two. The find() method is find_all() with limit=1. We can pass True or False values to find the methods. If we pass True to find_all(), it will return all tags in the soup object. In the case of find(), it will be the first tag within the object. The print(soup.find_all(True)) line of code will print out all the tags associated with the soup object. In the case of searching for text, passing True will return all text within the document as follows: all_texts = soup.find_all(text=True) print(all_texts) #output [u'n', u'n', u'n', u'n', u'n', u'plants', u'n', u'100000', u'n', u'n', u'n', u'algae', u'n', u'100000', u'n', u'n', u'n', u'n', u'n', u'deer', u'n', u'1000', u'n', u'n', u'n', u'rabbit', u'n', u'2000', u'n', u'n', u'n', u'n', u'n', u'fox', u'n', u'100', u'n', u'n', u'n', u'bear', u'n', u'100', u'n', u'n', u'n', u'n', u'n', u'lion', u'n', u'80', u'n', u'n', u'n', u'tiger', u'n', u'50', u'n', u'n', u'n', u'n', u'n'] The preceding output prints every text content within the soup object including the new-line characters too. Also, in the case of text, we can pass a list of strings and find_all() will find every string defined in the list: all_texts_in_list = soup.find_all(text=["plants","algae"]) print(all_texts_in_list) #output [u'plants', u'algae'] This is same in the case of searching for the tags, attribute values of tag, custom attributes, and the CSS class. For finding all the div and li tags, we can use the following code line: div_li_tags = soup.find_all(["div","li"]) Similarly, for finding tags with the producerlist and primaryconsumerlist classes, we can use the following code lines: all_css_class = soup.find_all(class_=["producerlist","primaryconsumerlist"]) Both find() and find_all() search an object's descendants (that is, all children coming after it in the tree), their children, and so on. We can control this behavior by using the recursive parameter. If recursive = False, search happens only on an object's direct children. For example, in the following code, search happens only at direct children for div and li tags. Since the direct child of the soup object is html, the following code will give an empty list: div_li_tags = soup.find_all(["div","li"],recursive=False) print(div_li_tags) #output [] If find_all() can't find results, it will return an empty list, whereas find() returns None. Navigation using Beautiful Soup Navigation in Beautiful Soup is almost the same as the searching methods. In navigating, instead of methods, there are certain attributes that facilitate the navigation. So each Tag or NavigableString object will be a member of the resulting tree with the Beautiful Soup object placed at the top and other objects as the nodes of the tree. The following code snippet is an example for an HTML tree: html_markup = """<div class="ecopyramid"> <ul id="producers"> <li class="producerlist"> <div class="name">plants</div> <div class="number">100000</div> </li> <li class="producerlist"> <div class="name">algae</div> <div class="number">100000</div> </li> </ul> </div>""" For the previous code snippet, the following HTML tree is formed: In the previous figure, we can see that Beautiful Soup is the root of the tree, the Tag objects make up the different nodes of the tree, while NavigableString objects make up the leaves of the tree. Navigation in Beautiful Soup is intended to help us visit the nodes of this HTML/XML tree. From a particular node, it is possible to: Navigate down to the children Navigate up to the parent Navigate sideways to the siblings Navigate to the next and previous objects parsed We will be using the previous html_markup as an example to discuss the different navigations using Beautiful Soup. Summary In this article, we discussed in detail the different search methods in Beautiful Soup, namely, find(), find_all(), find_next(), and find_parents(); code examples for a scraper using search methods to get information from a website; and understanding the application of search methods in combination. We also discussed in detail the different navigation methods provided by Beautiful Soup, methods specific to navigating downwards and upwards, and sideways, to the previous and next elements of the HTML tree. Resources for Article: Further resources on this subject: Web Services Testing and soapUI [article] Web Scraping with Python [article] Plotting data using Matplotlib: Part 1 [article]
Read more
  • 0
  • 0
  • 6692

article-image-your-first-application
Packt
15 Jan 2014
7 min read
Save for later

Your First Application

Packt
15 Jan 2014
7 min read
(For more resources related to this topic, see here.) Sketching out the application We are going to build a browsable database of cat profiles. Visitors will be able to create pages for their cats and fill in basic information such as the name, date of birth, and breed for each cat. This application will support the default Create-Retrieve-Update-Delete operations (CRUD). We will also create an overview page with the option to filter cats by breed. All of the security, authentication, and permission features are intentionally left out since they will be covered later. Entities, relationships, and attributes Firstly, we need to define the entities of our application. In broad terms, an entity is a thing (person, place, or object) about which the application should store data. From the requirements, we can extract the following entities and attributes: Cats, which have a numeric identifier, a name, a date of birth, and a breed Breeds, which only have an identifier and a name This information will help us when defining the database schema that will store the entities, relationships, and attributes, as well as the models, which are the PHP classes that represent the objects in our database. The map of our application We now need to think about the URL structure of our application. Having clean and expressive URLs has many benefits. On a usability level, the application will be easier to navigate and look less intimidating to the user. For frequent users, individual pages will be easier to remember or bookmark and, if they contain relevant keywords, they will often rank higher in search engine results. To fulfill the initial set of requirements, we are going to need the following routes in our application: Method Route Description GET / Index GET /cats Overview page GET /cats/breeds/:name Overview page for specific breed GET /cats/:id Individual cat page GET /cats/create Form to create a new cat page POST /cats Handle creation of new cat page GET /cats/:id/edit Form to edit existing cat page PUT /cats/:id Handle updates to cat page GET /cats/:id/delete Form to confirm deletion of page DELETE /cats/:id Handle deletion of cat page We will shortly learn how Laravel helps us to turn this routing sketch into actual code. If you have written PHP applications without a framework, you can briefly reflect on how you would have implemented such a routing structure. To add some perspective, this is what the second to last URL could have looked like with a traditional PHP script (without URL rewriting): /index.php?p=cats&id=1&_action=delete&confirm=true. The preceding table can be prepared using a pen and paper, in a spreadsheet editor, or even in your favorite code editor using ASCII characters. In the initial development phases, this table of routes is an important prototyping tool that forces you to think about URLs first and helps you define and refine the structure of your application iteratively. If you have worked with REST APIs, this kind of routing structure will look familiar to you. In RESTful terms, we have a cats resource that responds to the different HTTP verbs and provides an additional set of routes to display the necessary forms. If, on the other hand, you have not worked with RESTful sites, the use of the PUT and DELETE HTTP methods might be new to you. Even though web browsers do not support these methods for standard HTTP requests, Laravel uses a technique that other frameworks such as Rails use, and emulates those methods by adding a _method input field to the forms. This way, they can be sent over a standard POST request and are then delegated to the correct route or controller method in the application. Note also that none of the form submissions endpoints are handled with a GET method. This is primarily because they have side effects; a user could trigger the same action multiple times accidentally when using the browser history. Therefore, when they are called, these routes never display anything to the users. Instead, they redirect them after completing the action (for instance, DELETE /cats/:id will redirect the user to GET/cats). Starting the application Now that we have the blueprints for the application, let's roll up our sleeves and start writing some code. Start by opening a new terminal window and create a new project with Composer, as follows: $ composer create-project laravel/laravel cats --prefer-dist $ cd cats Once Composer finishes downloading Laravel and resolving its dependencies, you will have a directory structure identical to the one presented previously. Using the built-in development server To start the application, unless you are running an older version of PHP (5.3.*), you will not need a local server such as WAMP on Windows or MAMP on Mac OS since Laravel uses the built-in development server that is bundled with PHP 5.4 or later. To start the development server, we use the following artisan command: $ php artisan serve Artisan is the command-line utility that ships with Laravel and its features will be covered in more detail later. Next, open your web browser and visit http://localhost:8000; you will be greeted with Laravel's welcome message. If you get an error telling you that the php command does not exist or cannot be found, make sure that it is present in your PATH variable. If the command fails because you are running PHP 5.3 and you have no upgrade possibility, simply use your local development server (MAMP/WAMP) and set Apache's DocumentRoot to point to cats-app/public/. Writing the first routes Let's start by writing the first two routes of our application inside app/routes.php. This file already contains some comments as well as a sample route. You can keep the comments but you must remove the existing route before adding the following routes: Route::get('/', function(){   return "All cats"; }); Route::get('cats/{id}', function($id){   return "Cat #$id"; }); The first parameter of the get method is the URI pattern. When a pattern is matched, the closure function in the second parameter is executed with any parameters that were extracted from the pattern. Note that the slash prefix in the pattern is optional; however, you should not have any trailing slashes. You can make sure that your routes work by opening your web browser and visiting http://localhost:8000/cats/123. If you are not using PHP's built-in development server and are getting a 404 error at this stage, make sure that Apache's mod_rewrite configuration is enabled and works correctly. Restricting the route parameters In the pattern of the second route, {id} currently matches any string or number. To restrict it so that it only matches numbers, we can chain a where method to our route as follows: Route::get('cats/{id}', function($id){ return "Cat #$id"; })->where('id', '[0-9]+'); The where method takes two arguments: the first one is the name of the parameter and the second one is the regular expression pattern that it needs to match. Summary We have covered a lot in this article. We learned how to define routes, prepare the models of the application, and interact with them. Moreover, we have had a glimpse at the many powerful features of Eloquent, Blade, as well as the other convenient helpers in Laravel to create forms and input fields: all of this in under 200 lines of code! Resources for Article: Further resources on this subject: Laravel 4 - Creating a Simple CRUD Application in Hours [Article] Creating and Using Composer Packages [Article] Building a To-do List with Ajax [Article]
Read more
  • 0
  • 0
  • 1944

article-image-preparing-and-configuring-your-magento-website
Packt
10 Jan 2014
8 min read
Save for later

Preparing and Configuring Your Magento Website

Packt
10 Jan 2014
8 min read
(For more resources related to this topic, see here.) Focusing on your keywords We'll focus on three major considerations when choosing where to place our keywords within a Magento store: Purpose : What is the purpose of optimizing this keyword? Relevance : Is the keyword relevant to the page we have chosen to optimize it for? Structure : Does the structure of the website re-enforce the nature of our keyword? The purpose for choosing keywords to optimize on our Magento store must always be to increase our sales. It is true that (generically speaking) optimizing keywords means driving visitors to our website, but in the case of an e-commerce website, the end goal—the true justification of any SEO campaign—must be increasing the number of sales. We must then make sure that our visitors not just visit our website, but visit with the intention of buying something. The keywords we have chosen to optimize must be relevant to the page we are optimizing them on. The page, therefore, must contain elements specifically related to our keyword, and any unrelated material must be kept to a minimum. Driving potential customers to a page where their search term is unrelated to the content not only frustrates the visitor, but also lessens their desire to purchase from our website. The structure of our website must complement our chosen keyword. Competitive phrases, usually broader phrases with the highest search volume, are naturally the hardest to optimize. These types of keywords require a strong page to effectively optimize them. In most cases, the strength of a page is related to its level or tier within the URL. For example, the home page is normally seen as being the strongest page suitable for high search volume broad phrases followed by a tiered structure of categories, subcategories, and finally, product pages, as this diagram illustrates: With that said, we must be mindful of all three considerations when matching our keywords to our pages. As the following diagram shows, the relationship between these three elements is vital for ensuring not only that our keyword resides on a page with enough strength to enable it to perform, but also that it has enough relevance to retain our user intent at the same time as adhering to our overall purpose: The role of the home page You may be forgiven for thinking that optimizing our most competitive keyword on the home page would lead to the best results. However, when we take into account the relevance of our home page, does it really match our keyword? The answer is usually that it doesn't. In most cases, the home page should be used exclusively as a platform for building our brand identity . Our brand identity is the face of our business and is how customers will remember us long after they've purchased our goods and exited our website. In rare cases, we could optimize keywords on our home page that directly match our brand; for example, if our company name is "Wooden Furniture Co.", it might be acceptable to optimize for "Wooden Furniture" on our home page. It would also be acceptable if we were selling a single item on a single-page e-commerce website. In a typical Magento store, we would hope to see the following keyword distribution pattern: The buying intention of our visitors will almost certainly differ between each of these types of pages. Typically, a user entering our website via a broad phrase will have less of an intention to buy our products than a visitor entering our website through a more specific, product-related search term. Structuring our categories for better optimization Normally, our most competitive keywords will be classified as broad keywords, meaning that their relevance could be attributed to a variety of similar terms. This is why it makes sense to use top-level or parent categories as a basis for our broad phrases. To use our example, Wooden Furniture would be an ideal top-level category to contain subcategories such as 'Wooden Tables', 'Wooden Chairs', and 'Wooden Wardrobes', with content on our top-level category page to highlight these subcategories. On the Magento administration panel, go to Catalog | Manage Categories . Here, we can arrange our category structure to match our keyword relevance and broadness. In an ideal world, we would plan out our category structure before implementing it; sadly, that is not always the case. If we need to change our category structure to better match our SEO strategy, Magento provides a simple way to alter our category hierarchy. For example, say we currently have a top-level category called Furniture , and within this category, we have Wooden Furniture , and we decide that we're only optimizing for Wooden Furniture ; we can use Magento's drag-and-drop functionality to move Wooden Furniture to become a top-level category. To do this, we would have to perform the following steps: Navigate to Catalog | Manage Categories . Drag our Wooden Furniture category to the same level as Furniture . We will see that our URL has now changed from http://www.mydomain.com/furniture/wooden-furniture.html to http://www.mydomain.com/wooden-furniture.html. We will also notice that our old URL now redirects to our new URL; this is due to Magento's inbuilt URL Rewrite System. When moving our categories within the hierarchy, Magento will remember the old URL path that was specified and automatically create a redirect to the new location. This is fantastic for our SEO strategy as 301 redirects are vital for passing on authority from the old page to the new. If we wanted to have a look at these rewrites ourselves, we could perform the following steps: Navigate to Catalog | URL Rewrite Management . From the table, we could find our old request path and see the new target path that has been assigned. Not only does Magento keep track of our last URL, but any previous URLs also become rewritten. It is therefore not surprising that a large Magento store with numerous products and categories could have thousands upon thousands of rows within this table, especially when each URL is rewritten on a per-store basis. There are many configuration options within Magento that allow us to decide how and what Magento rewrites for us automatically. Another important point to note is that your category URL key may change depending on whether an existing category with the same URL key at the same level had existed previously in the system. If this situation occurs, an automatic incremental integer is appended to the URL key, for example, wooden-furniture-2.html. Magento Enterprise Edition has been enhanced to only allow unique URL keys. To know more, go to goo.gl/CKprNB. Optimizing our CMS pages CMS pages within Magento are primarily used as information pages. Terms and conditions, privacy policy, and returns policy are all examples of CMS pages that are created and configured within the Magento administration panel under CMS | Pages . By default, the home page of a Magento store is a CMS page with the title Home Page . The page that is served as the home page can be configured within the Magento Configuration under System | Configuration | Web | Default Pages . The most important part of a CMS page setup is that its URL key is always relative to the website's base URL. This means that when creating CMS pages, you can manually choose how deep you wish the page to exist on the site. This gives us the ability to create as many nested CMS pages as we like. Another important point to note is that, by default, CMS pages have no file extension (URL suffix) as opposed to the category and product URLs where we can specify which extension to use (if any). For CMS pages, the default optimization methods that are available to us are found within the Page Information tabs after selecting a CMS page: Under the Page Information subtab, we can choose our Page Title and URL key Under the Content subtab, we can enter our Content Heading (by default, this gets inserted into an <h1> tag) and enter our body content Under the Meta Data subtab, we can specify our keywords and description As mentioned previously, we would focus optimization on these pages purely for the intent of our users. If we were not using custom blocks or other methods to display product information, we would not optimize these information pages for keywords relating to purchasing a product. Summary In this article, we have learned the basic concepts of keyword placement and the roles of the different types of pages to prepare and configure your Magento website. Resources for Article : Further resources on this subject: Magento: Exploring Themes [Article] Magento : Payment and shipping method [Article] Integrating Twitter with Magento [Article]
Read more
  • 0
  • 0
  • 1493
article-image-marionette-view-types-and-their-use
Packt
07 Jan 2014
15 min read
Save for later

Marionette View Types and Their Use

Packt
07 Jan 2014
15 min read
(For more resources related to this topic, see here.) Marionette.View and Marionette.ItemView The Marionete.View extends the Backbone.View, and it's important to remember this, because all the knowledge that we already have on creating a view will be useful while working with these new set of views of Marionette. Each of them aims to provide a specific out of the box functionality so that you spend less time focusing on the glue code needed to make things work, and more time on things that are related to the needs of your application. This allows you to focus all your attention on the specific logic of your application. We will start by describing the Marionette.View part of Marionette, as all of the other views extend from it; the reason we do this is because this view provides a very useful functionality. But it's important to notice that this view is not intended to be used directly. As it is the base view from which all the other views inherit from, it is an excellent place to contain some of the glue code that we just talked about. A good example of that functionality is the close method, which will be responsible for removing .el from DOM. This method will also take care of calling unbind to all your events, thus avoiding the problem called Zombie views. This an issue that you can have if you don't do this carefully in a regular Backbone view, where new instantiations of previously closed fire events are present. These events remain bound to the HTML elements used in the view. These are now present again in the DOM now that the view has been rerendered, and during the recreation of the view, new event listeners are attached to these HTML elements. From the documentation of the Marionette.View, we exactly know what the close method does. It calls an onBeforeClose event on the view, if one is provided It calls an onClose event on the view, if one is provided It unbinds all custom view events It unbinds all DOM events It removes this.el from the DOM It unbinds all listenTo events The link to the official documentation of the Marionette.View object is https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.view.md. It's important to mention that the third point, unbind all custom view events, will unbind events created using the modelEvents hash, those created on the events hash, and events created via this.listenTo. As the close method is already provided and implemented, you don't need to perform the unbind and remove previously listed tasks. While most of the time this would be enough, at times, one of your views will need you to perform extra work in order to properly close it; in this case, two events will be fired at the same time to close a view. The event onBeforeClose, as the name indicates, will be fired just before the close method. It will call a function of the same name, onBeforeClose, where we can add the code that needs to be executed at this point. function : onBeforeClose () { // code to be run before closing the view } The second event will be onClose, which will be fired after the close method so that the .el of the view won't be present anymore and all the unbind tasks will have been performed. function : onClose () { // code to be run after closing the view } One of the core ideas behind Marionette is to reduce the boilerplate code that you have to write when building apps with Backbone. A perfect example of which is the render method that you have to implement in every Backbone view, and the code there is pretty much the same in each of your views. Load the template with the underscore _.template function and then pass the model converted to JSON to the template. The following is an example of repetitive code needed to render a view in Backbone: render : function () { var template = $( '#mytemplate' ).html(); var templateFunction = _.template( template ); var modelToJSON = this.model.toJSON(); var result = templateFunction(modelToJSON); var myElement = $( '#MyElement' ); myElement.html( result ); } As Marionette defining a render function is no longer required, just like the close method, the preceding code will be called for you behind the scenes. In order to render a view, we just need to declare it with a template property set. var SampleView = Backbone.Marionette.ItemView.extend({ template : '#sample-template' }); Next, we just create a Backbone model, and we pass it to the ItemView constructor. var SampleModel = Backbone.Model.extend({ defaults : { value1 : "A random Value", value2 : "Another Random Value" } }) var sampleModel = new SampleModel(); var sampleView = new SampleView({model:sampleModel); And then the only thing left is to call the render function. sampleView.render(); If you want to see it running, please go through this JSFiddle that illustrates the previous code: http://jsfiddle.net/rayweb_on/VS9hA/ One thing to note is that we just needed one line to specify the template, and Marionette did the rest by rendering our view with the specified template. Notice that in this example, we used the ItemView constructor; we should not use Marionette.View directly, as it does not have many functionalities of its own. It just serves as the base for other views. So some of the following examples of the functionalities provided by Marionette.View will be demonstrated using ItemView, as this view inherits all of these functionalities through extension. As we saw in the previous example, ItemView works perfectly for rendering a single model using a template, but what about rendering a collection of models? If you just need to render, for example, a list of books or categories, you still can use ItemView. To accomplish this, the template that you would assign to ItemView must know how to handle the creation of the DOM to properly display that list of items. Let's render a list of books. The Backbone model will have two properties: the book name and the book ID. We just want to create a list of links using the book name as the value to be displayed; the ID of the book will be used to create a link to see the specific book. First, let's create the book Backbone model for this example and its collection: var BookModel = Backbone.Model.extend({ defaults : { id : "1", name : "First", } }); var BookCollection = Backbone.Collection.extend({ model : BookModel }); Now let's instantiate the collection and add three models to it: var bookModel = new BookModel(); var bookModel2 = new BookModel({id:"2",name:"second"}); var bookModel3 = new BookModel({id:"3",name:"third"}); var bookCollection = new BookCollection(); bookCollection.add(bookModel); bookCollection.add(bookModel2); bookCollection.add(bookModel3); In our HTML, let's create the template to be used in this view; the template should look like the following: <script id="books-template" type="text/html"> <ul> <% _.each(items, function(item){ %> <li><a href="book/'+<%= item.id %> +"><%= item.name %> </li> <% }); %> </ul> </script> Now we could render the book list using the following code snippet: var BookListView = Marionette.ItemView.extend({ template: "#books-template" }); var view = new BookListView ({ collection: bookCollection }); view.Render(); If you want to see it in action, go to the working code in JSFiddle at http://jsfiddle.net/rayweb_on/8QAgQ/. The previous code would produce an unordered list of books with links to the specific book. Again, we gained the benefit of writing very little code once again, as we didn't need to specify the Render function, which could be misleading, because the ItemView is perfectly capable of rendering a model or a collection. Whether to use CollectionView or ItemView will depend on what we are trying to accomplish. If we need a set of individual views with its own functionality, CollectionView is the right choice, as we will see when we get to the point of reviewing it. But if we just need to render the values of a collection, ItemView would be the perfect choice. Handling events in the views To keep track of model events or collection events, we must write the following code snippet on a regular Backbone view: this.listenTo(this.model, "change:title", this.titleChanged); this.listenTo(this.collection, "add", this.collectionChanged); To start these events, we use the following handler functions: titleChanged: function(model, value){alert("changed");}, collectionChanged: function(model, value){alert("added");}, This still works fine in Marionette, but we can accomplish the same thing by declaring these events using the following configuration hash: modelEvents: { "change:title": "titleChanged" }, collectionEvents: { "add": "collectionChanged" }, This will give us exactly the same result, but the configuration hash is very convenient as we can keep adding events to our model or collection, and the code is cleaner and very easy to follow. The modelEvents and collectionEvents are not the only configuration hash sets that we have available in each one of the Marionette views; the UI configuration hash is also available. It may be the case that one of the DOM elements on your view will be used many times to read its value, and doing this using jQuery can not be optimal in terms of performance. Also, we would have the jQuery reference in several places, repeating ourselves and making our code less DRY. Inside a Backbone view, we can define a set of events that will be fired once an action is taken in the DOM; for instance, we pass the function that we want to handle in this event at the click of a button. events : { "click #button2" : "updateValue" }, This will invoke the updateValue function once we click on button2. This works fine, but what about calling a method that is not inside the view? To accomplish this, Marionette provides the triggers functionality that will fire events which can be listened to outside of your view. To declare a trigger, we can use the same syntax used in the events object as follows: triggers : { "click #button1": "trigger:alert"}, And then, we can listen to that event somewhere else using the following code: sampleView.on("trigger:alert", function(args){ alert(args.model.get("value2")); }); In the previous code, we used the model to alert and display the value of the property, value2. The args parameter received by the function will contain objects that you can use: The view that fired the trigger The Backbone model or collection of that view UI and templates While working with a view, you will need a reference to a particular HTML element through jQuery in more than one place in your view. This means you will make a reference to a button during initialization and in few other methods of the view. To avoid having the jQuery selector duplicated on each of these methods, you can map that UI element in a hash so that the selector is preserved. If you need to change it, the change will be done in a single place. To create this mapping of UI elements, we need to add the following declaration: ui: { quantity: "#quantity" saveButton : "#Save" }, And to make use of these mapper UI elements, we just need to refer them inside any function by the name given in the configuration. validateQuantity: function() { if (this.ui.quantity.val() > 0 { this.ui.saveButton.addClass('active'); } } There will be times when you need to pass a different template to your view. To do this in Marionette, we remove the template declaration and instead add a function called getTemplate. The following code snippet would illustrate the use of this function: getTemplate: function(){ if (this.model.get("foo"){ return "#sample-template"; }else { return "#a-different-template"; } }, In this case, we check the existence of the property foo; if it's not present, we use a different template and that will be it. You don't need to specify the render function because it will work the same way as declaring a template variable as seen in one of the previous examples. If you want to learn more about all the concepts that we have discussed so far, please refer to the jsFiddle link: http://jsfiddle.net/rayweb_on/NaHQS/. If you find yourself needing to make calculations involving a complicated process while rendering a value, you can make use of templeteHelpers that are functions contained in an object called templateHelpers. Let's look at an example that will illustrate its use better. Suppose we need to show the value of a book but are offering a discount that we need to calculate, use the following code: var PriceView = Backbone.Marionette.ItemView.extend({ template: "#price-template", templateHelpers: { calculatePrice: function(){ // logic to calculate the price goes here return price; } } }); As you can see the in the previous code, we declared an object literal that will contain functions that can be called from the templates. <script id="my-template" type="text/html"> Take this book with you for just : <%= calculatePrice () %> </script> Marionette.CollectionView Rendering a list of things like books inside one view is possible, but we want to be able to interact with each item. The solution for this will be to create a view one-by-one with the help of a loop. But Marionette solves this in a very elegant way by introducing the concept of CollectionView that will render a child view for each of the elements that we have in the collection we want to display. A good example to put into practice could be to list the books by category and create a Collection view. This is incredible easy. First, you need to define how each of your items should be displayed; this means how each item will be transformed in a view. For our categories example, we want each item to be a list <li> element and part of our collection; the <ul> list will contain each category view. We first declare ItemView as follows: var CategoryView = Backbone.Marionette.ItemView.extend({ tagName : 'li', template: "#categoryTemplate", }); Then we declare CollectionView, which specifies the view item to use. var CategoriesView = Backbone.Marionette.CollectionView.extend({ tagName : 'ul', className : 'unstyled', itemView: CategoryView }); A good thing to notice is that even when we are using Marionette views, we are still able to use the standard properties that Backbone views offer, such as tagName and ClassName. Finally, we create a collection and we instantiate CollectionView by passing the collection as a parameter. var categoriesView = new CategoriesView({collection:categories); categoriesView.render(); And that's it. Simple huh? The advantage of using this view is that it will render a view for each item, and it can have a lot of functionality; we can control all those views in the CollectionView that serves as a container. You can see it in action at http://jsfiddle.net/rayweb_on/7usdJ/. Marionette.CompositeView The Marionette.Composite view offers the possibility of not only rendering a model or collection models but, also the possibility of rendering both a model and a collection. That's why this view fits perfectly in our BookStore website. We will be adding single items to the shopping cart, books in this case, and we will be storing these books in a collection. But we need to calculate the subtotal of the order, show the calculated tax, and an order total; all of these properties will be part of our totals model that we will be displaying along with the ordered books. But there is a problem. What should we display in the order region when there are no items added? Well, in the CompositeView and the CollectionView, we can set an emptyView property, which will be a view to show in case there are no models in the collection. Once we add a model, we can then render the item and the totals model. Perhaps at this point, you may think that you lost control over your render functionality, and there will be cases where you need to do things to modify your HTML. Well, in that scenario, you should use the onRender() function, which is a very helpful method that will allow you to manipulate the DOM just after your render method was called. Finally, we would like to set a template with some headers. These headers are not part of an ItemView, so how can we display it? Let's have a look at part of the code snippet that explains how each part solves our needs. var OrderListView = Backbone.Marionette.CompositeView.extend({ tagName: "table", template: "#orderGrid", itemView: CartApp.OrderItemView, emptyView: CartApp.EmptyOrderView, className: "table table-hover table-condensed", appendHtml: function (collectionView, itemView) { collectionView.$("tbody").append(itemView.el); }, So far we defined the view and set the template; the Itemview and EmptyView properties will be used to render our view. The onBeforeRender is a function that will be called, as the name indicates, before the render method; this function will allow us to calculate the totals that will be displayed in the total model. onBeforeRender: function () { var subtotal = this.collection.getTotal(); var tax = subtotal * .08; var total = subtotal + tax; this.model.set({ subtotal: subtotal }); this.model.set({ tax: tax }); this.model.set({ total: total }); }, The onRender method is used here to check whether there are no models in the collection (that is, the user hasn't added a book to the shopping cart). If not, we should not display the header and footer regions of the view. onRender: function () { if (this.collection.length > 0) { this.$('thead').removeClass('hide'); this.$('tfoot').removeClass('hide'); } }, As we can see, Marionette does a great job offering functions that can remove a lot of boilerplate code and also give us full control over what is being rendered. Summary This article covered the introduction and usage of view types that Marionette has. Now you must be quite familiar with the Marionette.View and Marionette.ItemView view types of Marionette. Resources for Article: Further resources on this subject: Mobile Devices [Article] Puppet: Integrating External Tools [Article] Understanding Backbone [Article]
Read more
  • 0
  • 0
  • 2078

article-image-creating-identity-and-resource-pools
Packt
24 Dec 2013
7 min read
Save for later

Creating Identity and Resource Pools in Cisco Unified Computing System

Packt
24 Dec 2013
7 min read
Computers and their various peripherals have some unique identities such as Universally Unique Identifiers (UUIDs), Media Access Control (MAC) addresses of Network Interface Cards (NICs), World Wide Node Numbers (WWNNs) for Host Bus Adapters (HBAs), and others. These identities are used to uniquely identify a computer system in a network. For traditional computers and peripherals, these identities were burned into the hardware and, hence, couldn't be altered easily. Operating systems and some applications rely on these identities and may fail if these identities are changed. In case of a full computer system failure or failure of a computer peripheral with unique identity, administrators have to follow cumbersome firmware upgrade procedures to replicate the identities of the failed components on the replacement components. The Unified Computing System (UCS) platform introduced the idea of creating identity and resource pools to abstract the compute node identities from the UCS Manager (UCSM) instead of using the hardware burned-in identities. In this article, we'll discuss the different pools you can create during UCS deployments and server provisioning. We'll start by looking at what pools are and then discuss the different types of pools and show how to configure each of them. Understanding identity and resource pools The salient feature of the Cisco UCS platform is stateless computing . In the Cisco UCS platform, none of the computer peripherals consume the hardware burned-in identities. Rather, all the unique characteristics are extracted from identity and resource pools, which reside on the Fabric Interconnects (FIs) and are managed using UCSM. These resource and identity pools are defined in an XML format, which makes them extremely portable and easily modifiable. UCS computers and peripherals extract these identities from UCSM in the form of a service profile. A service profile has all the server identities including UUIDs, MACs, WWNNs, firmware versions, BIOS settings, and other server settings. A service profile is associated with the physical server using customized Linux OS that assigns all the settings in a service profile to the physical server. In case of server failure, the failed server needs to be removed and the replacement server has to be associated with the existing service profile of the failed server. In this service profile association process, the new server will automatically pick up all the identities of the failed server, and the operating system or applications dependent upon these identities will not observe any change in the hardware. In case of peripheral failure, the replacement peripheral will automatically acquire the identities of the failed component. This greatly improves the time required to recover a system in case of a failure. Using service profiles with the identity and resource pools also greatly improves the server provisioning effort. A service profile with all the settings can be prepared in advance while an administrator is waiting for the delivery of the physical server. The administrator can create service profile templates that can be used to create hundreds of service profiles; these profiles can be associated with the physical servers with the same hardware specifications. Creating a server template is highly recommended as this greatly reduces the time for server provisioning. This is because a template can be created once and used for any number of physical servers with the same hardware. Server identity and resource pools are created using the UCSM. In order to better organize, it is possible to define as many pools as are needed in each category. Keep in mind that each defined resource will consume space in the UCSM database. It is, therefore, a best practice to create identity and resource pool ranges based on the current and near-future assessments. For larger deployments, it is best practice to define a hierarchy of resources in the UCSM based on geographical, departmental, or other criteria; for example, a hierarchy can be defined based on different departments. This hierarchy is defined as an organization, and the resource pools can be created for each organizational unit. In the UCSM, the main organization unit is root, and further suborganizations can be defined under this organization. The only consideration to be kept in mind is that pools defined under one organizational unit can't be migrated to other organizational units unless they are deleted first and then created again where required. The following diagram shows how identity and resource pools provide unique features to a stateless blade server and components such as the mezzanine card: Learning to create a UUID pool UUID is a 128-bit number assigned to every compute node on a network to identify the compute node globally. UUID is denoted as 32 hexadecimal numbers. In the Cisco UCSM, a server UUID can be generated using the UUID suffix pool. The UCSM software generates a unique prefix to ensure that the generated compute node UUID is unique. Operating systems including hypervisors and some applications may leverage UUID number binding. The UUIDs generated with a resource pool are portable. In case of a catastrophic failure of the compute node, the pooled UUID assigned through a service profile can be easily transferred to a replacement compute node without going through complex firmware upgrades. Following are the steps to create UUIDs for the blade servers: Log in to the UCSM screen. Click on the Servers tab in the navigation pane. Click on the Pools tab and expand root. Right-click on UUID Suffix Pools and click on Create UUID Suffix Pool as shown in the following screenshot: In the pop-up window, assign the Name and Description values to the UUID pool. Leave the Prefix value as Derived to make sure that UCSM makes the prefix unique. The selection of Assignment Order as Default is random. Select Sequential to assign the UUID sequentially. Click on Next as shown in the following screenshot: Click on Add in the next screen. In the pop-up window, change the value for Size to create a desired number of UUIDs. Click on OK and then on Finish in the previous screen as shown in the following screenshot: In order to verify the UUID suffix pool, click on the UUID Suffix Pools tab in the navigation pane and then on the UUID Suffixes tab in the work pane as shown in the following screenshot: Learning to create a MAC pool MAC is a 48-bit address assigned to the network interface for communication in the physical network. MAC address pools make server provisioning easier by providing scalable NIC configurations before the actual deployment. Following are the steps to create MAC pools: Log in to the UCSM screen. Click on the LAN tab in the navigation pane. Click on the Pools tab and expand root. Right-click on MAC Pools and click on Create MAC Pool as shown in the following screenshot: In the pop-up window, assign the Name and Description values to the MAC pool. The selection of Default as the Assignment Order value is random. Select Sequential to assign the MAC addresses sequentially. Click on Next as shown in the following screenshot: Click on Add in the next screen. In the pop-up window, change Size to create the desired number of MAC addresses. Click on OK and then on Finish in the previous screen as shown in the following screenshot: In order to verify the MAC pool, click on the MAC Pools tab in the navigation pane and then on the MAC Addresses tab in the work pane as shown in the following screenshot:
Read more
  • 0
  • 0
  • 2413