Start a first project for cloud application in visual studio

If you dont have Windows Azure Tools installed

1. Open Visual Studio 2010

2. On the File Menu, Click new, and then click Project. This opens the New Project dialog

3. In the New Project dialog under Installed Templates, expand the Visual C# node

4. In project type click Cloud. A project that says Enable Windows Azure Tools appears

5. In Name type for example EnableTools and click OK

6. A project with a web page will appear. Click the Download Windows Azure Tools button. Close Visual Studio. Download and installed them.

image

Once you have Windows Azure Toolsl installed

1. Open Visual Studio 2010

2. On the File Menu, Click new, and then click Project. This opens the New Project dialog

3. In the New Project dialog under Installed Templates, expand the Visual C# node

4. In project type click Cloud. A project that says Windows Azure Cloud Service appears

image

5. In Name Type for example Phonebook and click ok. The New Cloud Service Project is shown

If you are developing a Silverlight application with some services select the WCF Service Web Role. Rename it to something appropriate. In this example will be Phonebook.Web and Press OK

image

Your solution explorer will look like this:

image

Now you can developing your application. We already have an Silverlight application (that was migrated from VB6 to Silverlight) and some existing Silverlight Class libraries and Server Class Libraries (Class Libraries compiled with the full 4.0 Framework that will be used in the Server Project Phonebook.Web).

To add your Silverlight app. Right Click your server project (Phonebook.Web), then Properties and in Properties go to Silverlight Application and add Phonebook_Silverlight

When everything compiles Go to the Visual Studio Menu Bar, then Debug and then Start Without Debugging. That starts the local development environment on your computer.

image

You can now start testing and finish development of your application.

There is something you myst notice. Everytime you start the Cloud Service, the Azure test environment starts. By default it will start in http:\\localhost:81 but there was a previous Development Fabric it will start in http:\\localhost:81. This is important for Silverlight applications because you must configure your service end point to a particular port. Make sure that your ServiceReferences.ClientConfig file is in sync with the port that your DevelopmentFabric is using

Notes for Azure development: 

Sometimes during development it might happen that you get more than one instance of the Development Fabric. This will affect your silverlight apps that rely on WFC services because each new instance starts on a new port. You can use the CSRun tool to stop all instances.

If you have installed the Windows® Azure™ SDK to the default location, the CSRun tool can be found at C:\Program Files\Windows Azure SDK\v1.0\bin\csrun.exe.Then run C:\Program Files\Windows Azure SDK\v1.2\bin\csrun.exe /devfabric:shutdown

Publishing your Application

1. Navigate to Azure : https://windows.azure.com/Cloud/Provisioning/Default.aspx

2. On the page that says My Projects. When you are starting you will only see one project line. Click on it

image

3. Click on New Service

image

4. Click on Hosted Services

image

5. In the Create Service page, specify the service properties. In this example we will use Phonebook.Web for service label and a short description and press next.

image

6. Now your hosted service needs a public url. You must check availability. In this example we will use phonebook. Hosted Affinity tries to group your services and storages in the same area. We have a SQL Azure database that is hosted in North Central US, so we will create a new AffinityGroup and call it PhonebookGroup. Press Create

image

7. After Creation your Service is ready, and you can start the deployment.

image

8. In Visual Studio 2010 Right click your Cloud Service. And Select Publish…

image

9. The Publish Cloud Service Dialog appears. From the Credentials drop down list select <Add>

image

10. From the Create or select an existing certificate select <Create>.
10.1 In our example we will enter a FriendlyName for the new certificate of PhoneBook.

image
10.2 Click the “Copy the full path” link in the dialog. Then Open your browser and navigate tohttps://windows.azure.com/cloud/provisioning/ and click on your project

image

10.3 Now click on account.And in the Account page click on Manage My API Certificates

image

10.4 Click the Choose file and paste the full path you had copied before and then click upload

image

the installed certificate will be shown below.

image

10.5 Now navigate to AppFabric by clicking AppFabric on the left hand side. This will show your subscription ID. Select it and copy it. You have to pasted on the dialog box in Visual Studio on the textbox that says above it “Copy the subscription ID”

image

and name those Credentials PhonebookAccount and press  OK

11 You need a storage account. If you have not created one. Then you have to follow these steps:

11.1 Open your browser and navigate to https://windows.azure.com/cloud/provisioning/ and click on your project.

image

11.2 Now click on New Service

image

11.3 Now click on Storage Account

image

11.4 The Create Service Page is show. Enter a Service label and Description and Click Next

image

11.5 Select a name for the public URL, check its availability. And select Affinity.And press Create

image

12. Press OK on the Publish Cloud Service Dialog

image

13. Visual studio will upload your application to the cloud

image

While your application is in staging the only problem might be that the published URL changed and that might be conflictive for your ServiceReferences.ClientConfig.

Once your application is on Staging you can switch it to Production and your are ready for business.

A Toy Sales Order Entry & Processing System

I give below the functional specifications for a toy sales order entry and processing system. The specifications given are for the logical aspects of the system only, and therefore are, incomplete. They are also incomplete in that the behavior model is absent. They are given as illustrations only. They consist of:

  • Context diagram
  • levelled logical dataflow diagrams
  • Relation specifications for a Relational Database
  • Specifications for the dataflows
  • Process descriptions in raw prolog code. (Prolog is a relational language. The code is given
    here, since prolog code is generally easily grasped). The code given here, with very minor
    changes, should be executable.

I will not provide the physical DFDs below, since they are implementation dependent, and I have not based this toy system on any real-world accounting system.

We have yet to discuss the data models and databases. We will not be discussing programming aspects of systems. Therefore, the database specifications are given as a prelude to our class discussions on databases later in the semester. The code is given just for the purpose of appreciation.

We are talking about a very small firm that considers orders from customers for one item. You should be able to add bells and whistles as you wish. The situation considered is rather unrealistic, but it makes important points about specifications for an accounting system and its documentation.

Table of Contents

  • Context Diagram
  • Level 0 Logical Dataflow Diagram
  • Level 1 Logical DFD: Sales Order Entry Sub-system
  • Level 1 Logical DFD: Sales Order Processing Sub-system
  • Dataflow Specifications
  • Datastore Specifications
  • Process Specifications

Context Diagram: (Sales Order Entry & Processing System)

Level 0 Logical Dataflow Diagram:(Sales Order Entry & Processing System)

Level 1 Logical Dataflow Diagram:(Sales Order Entry Sub-system)

Level 1 Logical Dataflow Diagram:(Sales Order Processing Sub-system)

Dataflow Specifications

Syntax: dataflowName(attribute1, attribute2,…..)

order(CustomerName, CustomerAddress, Item, Quantity)
pricedOrder(CustomerName, CustomerAddress, Item, Quantity, OrderPrice)
weDontSell(CustomerName, CustomerAddress, Item)
sorryBadCredit(CustomerName, CustomerAddress)
approvedOrder(CustomerName, CustomerAddress, Item, Quantity, OrderPrice)
sorryNotInStock(CustomerName, CustomerAddress, Item)
acceptedOrder(CustomerName, CustomerAddress, Item, Quantity, OrderPrice)
salesOrder(CustomerName, CustomerAddress, Item, Quantity, OrderPrice)
billOfLading(CustomerName, CustomerAddress, Item, Quantity)
invoice(CustomerName, CustomerAddress, Item, Quantity, OrderPrice)

Datastore Specifications

Syntax:relationName(attribute1, attribute2,……)

priceList(Item, Price)
customerMaster(CustomerName, CustomerAddress, Balance, CreditLimit)
inventoryMaster(Item, QuantityOnHand)
salesOrderMaster(CustomerName, Item, Quantity, OrderPrice)
billOfLading(CustomerName, Item, Quantity)
openInvoices(CustomerName, Item, Quantity, OrderPrice)
customer(CustomerName, CustomerAddress)
order(CustomerName, CustomerAddress, Item, Quantity)

Process Specifications:

Syntax:prolog clause
/*    Orders are priced by multiplying the quantity ordered by the */
/*    price for the item on the price list               */

pricedOrder(CustomerName, CustomerAddress, Item, Quantity, OrderPrice)
      if
         order(CustomerName, CustomerAddress, Item, Quantity),
         priceList(Item, Price),
         orderPrice is Price * Quantity.

/*  We don't sell the item ordered by the customer if such item   */
/*  is not on the price list                 */

weDontSell(CustomerName, CustomerAddress, Item)
      if
         order(CustomerName, CustomerAddress, Item, Quantity),
         not priceList(Item, _).

/*  A customer order for an item is approved if the order is priced         */
/*  and the account balance after the order is less than the credit limit  */

approvedOrder(CustomerName, CustomerAddress, Item, Quantity, OrderPrice)
      if
         pricedOrder(CustomerName, CustomerAddress, Item, Quantity, OrderPrice),
         customerMaster(CustomerName, CustomerAddress, Balance, CreditLimit),
         NewBalance is Balance + OrderPrice,
         NewBalance < CreditLimit.

/*  A customer order is rejected on account of bad credit if the  */
/*  order is priced and the account balance after the order         */
/*  exceeds the credit limit for the customer                                  */

sorryBadCredit(CustomerName, CustomerAddress)
      if
         pricedOrder(CustomerName, CustomerAddress, Item, Quantity, OrderPrice),
         customerMaster(CustomerName, CustomerAddress, Balance, CreditLimit),
         NewBalance is Balance + OrderPrice,
         NewBalance >= CreditLimit.

/*  A customer order is accepted if it is approved and the quantity on      */
/*  hand of the item ordered is at least as much as the quantity ordered  */

acceptedOrder(CustomerName, CustomerAddress, Item, Quantity, OrderPrice)
      if
         approvedOrder(CustomerName, CustomerAddress, Item, Quantity, OrderPrice),
         inventoryMaster(Item, QuantityOnHand),
         QuantityOnHand >= Quantity.

/*  A sales order is prepared if a customer order is accepted  */

salesOrder(CustomerName, CustomerAddress, Item, Quantity, OrderPrice)
      if
         acceptedOrder(CustomerName, CustomerAddress, Item, Quantity, OrderPrice),

/*  A bill of lading is prepared if a sales order is prepared   */

billOfLading(CustomerName, CustomerAddress, Item, Quantity)
      if
         salesOrder(CustomerName, CustomerAddress, Item, Quantity, OrderPrice).

/*  An open invoice is prepared if a bill of lading is prepared  */

openInvoices(CustomerName, Item, Quantity, OrderPrice)
      if
         billOfLading(CustomerName, CustomerAddress, Item, Quantity).

/*  A customer's account is updated by adding the order price to the   */
/*  current balance in the account if open invoice is prepared               */

updateCustomerAccountsForInvoices
      if
         openInvoices(CustomerName, Item, Quantity, OrderPrice),
         retract(customerMaster(CustomerName, CustomerAddress, Balance, CreditLimit)),
         NewBalance is Balance + OrderPrice,
         assert(customerMaster(CustomerName, CustomerAddress, NewBalance, CreditLimit)).

References

Alexander, C. (1971). Notes on the Synthesis of Form, 2d ed. Cambridge, MA: Harvard University Press.

Alexander, C. (1979). A Timeless Way of Building. New York, NY: Oxford University Press.

Eberhard, J. (1970) “We Ought to Know the Difference”, in Engineering Methods in Environmental Design and Planning, Gary T. Moore, ed. Cambridge, Mass.: MIT Press. pp.364-365.

Harel, D. (1987). Statecharts: A Visual Formalism for Complex Systems. Science of Computer Programming, pp.231-274.

Horner, K. (1993). Methodology as a Productivity Tool, in Software Productivity Handbook, J. Keyes (ed), New York, NY: Windcrest/McGraw-Hill, pp.97-117.

Pressman, R. (1987). Software Engineering: A Practitioner’s Approach, 2d ed. New York, NY: McGraw-Hill.

Teague, L and C. Pidgeon. (1985) Structured Analysis Methods for Computer Information Systems. Chicago, Ill.: Science Research Associates.

Yourdon, E. (1989) Modern Structured Systems Analysis. Englewood Cliffs, NJ: Prentice Hall.

Yourdon, E. (1993). A Natural Productivity in Object-Orientation, in Software Productivity Handbook, J. Keyes (ed), New York, NY: Windcrest/McGraw-Hill, pp.97-117.

Systems Analysis & Design (1)

My experience has shown that many people find it hard to make their design ideas precise. They are willing to express their ideas in loose, general terms, but are unwilling to express them with the precision needed to make them into patterns. Above all, they are unwilling to express them as abstract spatial relations among well-defined spatial parts. I have also found that people aren’t always very good at it; it is hard to do….. If you can’t draw a diagram of it, it isn’t a pattern. If you think you have a pattern, you must be able to draw a diagram of it. This is a crude, but vital rule. A pattern defines a field of spatial relations, and it must always be possible to draw a diagram for every pattern. In the diagram, each part will appear as a labeled or colored zone, and the layout of the parts expresses the relation which the pattern specifies. If you can’t draw it, it isn’t a pattern.

Christopher Alexander (1979) in The Timeless Way of Building.

One anxiety inherent in the design methods is the hierarchical nature of complexity. This anxiety moves in two directions, escalation and infinite regression. I will use a story, “The Warning of the Doorknob,” to illustrate the principle of escalation.

This has been my experience in Washington when I had money to give away. If I gave a contract to a designer and said, “The doorknob to my office doesn’t have much imagination, much design content. Will you design me a new doorknob?” He would say “Yes,” and after we establish a price he goes away. A week later he comes back and says, “Mr. Eberhard, I have been thinking about that doorknob. First we ought to ask ourselves whether a doorknob is the best way of opening and closing a door.” I say, “Fine, I believe in imagination, go to it.” He comes back later and says, “You know, I have been thinking about your problem, and the only reason you want a doorknob is you presume you want a door to your office. Are you sure that a door is the best way of controlling egress, exit, and privacy?” “No, I’m not sure at all.” “Well, I want to worry about that problem.” He comes back a week later and says, “The only reason we have to worry about the aperture problem is that you insist on having four walls around your office. Are you sure that is the best way of organizing this space for the kind of work you do as a bureaucrat?” I say, “No, I’m not sure at all.” Well, this escalates until (and this has literally happened in two contracts, although not exactly through this process) our physical designer comes back with a very serious face. “Mr. Eberhard, we have to decide whether capitalistic democracy is the best way to organize our country before I can possibly attack your problem.”

On the other hand is the problem of infinite regression. If this man faced with the design of the doorknob had said, “Wait. Before I worry about the doorknob, I want to study the shape of man’s hand and what a man is capable of doing with it,” I would say, “Fine.” He would come back and say, “The more I thought about it, there’s a fit problem. What I want to study first is how metal is formed, what the technologies are for making things with metal in order that I can know what the real parameters are for fitting the hand.” “Fine.” But then he says, “You know, I have been looking at metal forming and it all depends on metallurgical properties. I really want to spend three or four months looking at metallurgy so that I can understand the problem better.” “Fine.” After three months he will come back and say, “Mr. Eberhard, the more I look at metallurgy, the more I realize that it is the atomic structure that’s really at the heart of this problem.” And so, our physical designer is in atomic physics from the doorknob. That is one of our anxieties, the hierarchical nature of complexity.

Eberhard (1970) quoted in Teague & Pidgeon (1985) and Yourdon (1989).

Introduction

The work of Christopher Alexander, a mathematician-turned architect, has had a subtle and yet a profound impact on the methodologies for the development of information systems in business. The main idea in architecture, espoused by Alexander, is that buildings and cities can be designed from the combination of certain basic patterns. Such patterns can be documented as diagrams which, in the architectural domain, specify spatial relationships. In the domain of business (and accounting) information systems development, the task is to create languages for describing and manipulating patterns to create systems that meet the needs of business.

In this note, we shall study the way in which information systems are specified, and the methodology of Systems Development Life Cycle (SDLC) that is often used in the development of accounting information systems.

Specification of Information Systems

Why specifications?

Specification of any system before its development is crucial. Specifications perform for information systems the same function that blue-prints and engineering specifications perform for physical structures. Specifications serve as benchmarks for evaluating designs as well as their implementation. They also facilitate quality assurance via verification (are we building the system right, ie., do the design and implementation meet the specifications?) and validation ( are we building the right system, ie., does the system meet the user needs?).

Components of specifications

Specification of an information system is given by their

  • Structure: How it is organised.
  • Function: What it does.
  • Behavior: How it responds to events and stimuli.
  • Data: Its meaning and organization.

Most CASE tools co-ordinate information systems projects through a project or system dictionary. The function of the dictionary is to standardise the use of terms throughout the organisation and to serve as a repository of all common information in the project. It enforces consistency as well as (relative) completeness of the specifications, and facilitates verification & validation of such specifications. It also serves as a means of communication between the different persons on the information systems building team.The figure below shows the various components of the specifications and the modeling techniques utilised. We will be studying some of those techniques in this course.

Methodologies for Systems Development

There are many methodologies for the development of information systems: Systems Development Life Cycle (SDLC), Data Structure-Oriented design, Object-Oriented design, Prototyping, among others. We shall, however, be concerned here primarily with SDLC.

Systems Development Life Cycle:

Referred to variously as the waterfall model and linear cycle, this methodology is a coherent description of the steps taken in the development of information systems. The reason why it is referred to as the waterfall model should be obvious from the following figure (from Horner, 1993):

The methodology SDLC is closely linked to what has come to be known as structured systems analysis & design. It involves a series of steps to be undertaken in the development of information systems as follows:

  • Problem definition: On receiving a request from the user for systems development, an investigation is conducted to state the problem to be solved.
    • Deliverables: Problem statement.
  • Feasibility study: The objective here is to clearly define the scope and objectives of the systems project, and to identify alternative solutions to the problem defined earlier.
    • Deliverables: Feasibility report.
  • Systems analysis phase: The present system is investigated and its specifications documented. They should contain our understanding of HOW the present system works and WHAT it does.
    • Deliverables: Specifications of the present system.
  • Systems design phase: The specifications of the present system are studied to determine what changes will be needed to incorporate the user needs not met by the system presently. The output of this phase will consist of the specifications, which must describe both WHAT the proposed system will do and HOW it will work.of the proposed system.
    • Deliverables:Specifications of the proposed system.
  • Systems construction: Programming the system, and development of user documentation for the system as well as the programs.
    • Deliverables: Programs, their documentation, and user manuals.
  • System testing & evaluation: Testing, verification and validation of the system just built.
    • Deliverables: Test and evaluation results, and the system ready to be delivered to the user/client.

The figure below provides an illustration for the above description.

The waterfall model has many attractive features:

  • Clearly defined deliverables at the end of each phase, so that the client can take decisions on continuing the project.
  • Incremental resource committment. The client does not have to make a full committment on the project at the beginning.
  • Isolation of the problem early in the process.

It does, however, have some drawbacks:

  • Requires an all-or-nothing approach to systems development. Does not allow incremental development.
  • Requires very early isolation of the problem. In the real world, often the problems are uncovered in the process of development of systems.

Strategy in Analysis & Design

The understanding and management of complexity is perhaps the most important task of the designer of an information system. It is carried out bearing in mind the strategies of abstraction as well as hierarchical ordering (divide & conquer).

In the real world, an accounting information systems designer (systems designer for short) is rarely called upon to analyse and design a system from the scratch. Usually, such a system does exist, but the client (user) is not quite satisfied with it. The systems designer starts with the documentation of the existing accounting system, if it does not exist. Often, documentation pertaining to the existing system is contained in the audit workpapers pertaining to the auditor’s study of control risk assessment. However, since such documentation is not prepared with a view to design a system, it is used only as a starting point in building the documentation to aid systems design.

In this document, we shall study how abstraction and hierarchical ordering strategies are used to manage the complexity of analysing and designing the functions of an information system.

The methodology of structured systems analysis & design provides a roadmap for the development of functional specifications for an accounting information system, shown in the Figure below.

The functional specifications are documented graphically in Dataflow Diagrams (DFDs)
described in the next section below.

STEP 0: (Defining the scope of the system under study.) This accomplished by drawing the context diagram for the system.

STEP 1: (Documentation of how the existing system works.) This is accomplished by drawing the Physical DFDs of the existing system. These DFDs specify the current implementation of the existing system, and would answer questions such as:

  • Who performs the tasks?
  • How they are performed?
  • When or how often they are performed?
  • How the data is stored (media)?
  • How the dataflows are implemented (media)?

These physical DFDs may be levelled, or, if the system is not very large, prepared all on a single DFD.

STEP 2: (Documentation of what the existing system does.)This is documented in Logical DFDs of the existing system. Deriving these logical DFDs of the existing system from the physical DFDs involve abstraction of all implementation details. Since the systems designer would not like to be tied down by the current implementation of the system, all such details are abstracted. These logical DFDs are usually levelled in order to reduce the perceived complexity of the system, and balanced in order to assure consistency in the design.

STEP 3: (Documentation of what the proposed system will do.) After step 2, the systems designer will examine why the existing system does not meet the user requirements, and how it can be modified in order to meet such needs. The result is a set of logical DFDs which describe what the modified (proposed) system will do. These functional specifications are devoid of implementation considerations, and therefore rather abstract specifications of the proposed system. These logical DFDs are also levelled and balanced.

STEP 4: (Documentation of how the proposed system will work.) The logical DFDs of the proposed system derived in step 3 above are then examined to determine which implementation of it meets the user requirements most efficiently. The result is a set of physical DFDs of the proposed system. They answer questions such as:

  • Who will perform the various tasks?
  • How they will be performed?
  • When or how often they will be performed?
  • How the data will be stored (media)?
  • How the dataflows will be implemented (media)?

In this step, man-machine boundaries are drawn, and media selected for all dataflows & datastores.

The function of any information system can be expressed in terms of transformation (processing) of certain inputs (which are data) into outputs (which are data too) where memory (which too consists of data) may need to be consulted (or updated). This suggests that two crucial elements in a system’s description are data and processing of data. A complete description of an information system demands description of both these elements. In fact, we can reduce this, in a mundane fashion to the equation:

System = Data + Processing of data

While it is impossible to describe an information system exclusively in terms of data or its processing, it is possible to study a system’s functions (what the system must do) in terms of the transformations it must perform of the data which is modeled separately. A coherent description of the information system, however, would require that the models of data and its processing are not inconsistent. An information system’s functions, which describe its processing aspects, is modeled in the structured systems approach, as dataflow diagrams.Such a model of an information system is, for obvious reasons, referred to as functional model or process model.

A dataflow diagram consists of external entities (represented by rectangles), processes (represented by either rounded rectangles or circles), data stores (represented by either an open rectangle or two parallel lines) and dataflows (represented by arrows).

Detecting HTML5 Features

DIVING IN

You may well ask: “How can I start using HTML5 if older browsers don’t support it?” But the question itself is misleading. HTML5 is not one big thing; it is a collection of individual features. So you can’t detect “HTML5support,” because that doesn’t make any sense. But you can detect support for individual features, like canvas, video, or geolocation.

DETECTION TECHNIQUES

When your browser renders a web page, it constructs a Document Object Model (DOM), a collection of objects that represent the HTML elements on the page. Every element — every <p>, every <div>, every <span> — is represented in the DOM by a different object. (There are also global objects, like window and document, that aren’t tied to specific elements.)

girl peeking out the window

All DOM objects share a set of common properties, but some objects have more than others. In browsers that support HTML5 features, certain objects will have unique properties. A quick peek at the DOM will tell you which features are supported.

There are four basic techniques for detecting whether a browser supports a particular feature. From simplest to most complex:

  1. Check if a certain property exists on a global object (such as window ornavigator).

    Example: testing for geolocation support

  2. Create an element, then check if a certain property exists on that element.

    Example: testing for canvas support

  3. Create an element, check if a certain method exists on that element, then call the method and check the value it returns.

    Example: testing which video formats are supported

  4. Create an element, set a property to a certain value, then check if the property has retained its value.

    Example: testing which <input> types are supported

MODERNIZR, AN HTML5 DETECTION LIBRARY

Modernizr is an open source, MIT-licensed JavaScript library that detects support for many HTML5 & CSS3 features. At the time of writing, the latest version is 1.5. You should always use the latest version. To use it, include the following <script>element at the top of your page.

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Dive Into HTML5</title> <script src="modernizr.min.js"></script> </head> <body> ... </body> </html> 

↜ It goes to your <head>

Modernizr runs automatically. There is no modernizr_init() function to call. When it runs, it creates a global object calledModernizr, that contains a set of Boolean properties for each feature it can detect. For example, if your browser supports thecanvas API, the Modernizr.canvas property will be true. If your browser does not support the canvas API, theModernizr.canvas property will be false.

if (Modernizr.canvas) { // let's draw some shapes! } else { // no native canvas support available :( }

CANVAS

man fishing in a canoe
Your browser supports the canvas API.

HTML5 defines the <canvas> element as “a resolution-dependent bitmap canvas that can be used for rendering graphs, game graphics, or other visual images on the fly.” A canvas is a rectangle in your page where you can use JavaScript to draw anything you want. HTML5 defines a set of functions (“the canvas API”) for drawing shapes, defining paths, creating gradients, and applying transformations.

Checking for the canvas API uses detection technique #2. If your browser supports the canvas API, the DOM object it creates to represent a <canvas> element will have a getContext() method. If your browser doesn’t support the canvas API, theDOM object it creates for a <canvas> element will only have the set of common properties, but not anything canvas-specific.

function supports_canvas() { return !!document.createElement('canvas').getContext; } 

This function starts by creating a dummy <canvas> element. But the element is never attached to your page, so no one will ever see it. It’s just floating in memory, going nowhere and doing nothing, like a canoe on a lazy river.

return !!document.createElement('canvas').getContext;

As soon as you create the dummy <canvas> element, you test for the presence of a getContext() method. This method will only exist if your browser supports the canvas API.

return !!document.createElement('canvas').getContext;

Finally, you use the double-negative trick to force the result to a Boolean value (true or false).

return !!document.createElement('canvas').getContext;

This function will detect support for most of the canvas API, including shapespathsgradients & patterns. It will not detect the third-party explorercanvas library that implements the canvas API in Microsoft Internet Explorer.

Instead of writing this function yourself, you can use Modernizr to detect support for the canvas API.

↶ check for canvas support

if (Modernizr.canvas) { // let's draw some shapes! } else { // no native canvas support available :( }

There is a separate test for the canvas text API, which I will demonstrate next.

CANVAS TEXT

baseball player at bat
Your browser supports the canvas text API.

Even if your browser supports the canvas API, it might not support the canvas text API. The canvas API grew over time, and the text functions were added late in the game. Some browsers shipped with canvas support before the text API was complete.

Checking for the canvas text API uses detection technique #2. If your browser supports the canvas API, the DOM object it creates to represent a <canvas> element will have the getContext() method. If your browser doesn’t support the canvas API, the DOM object it creates for a <canvas> element will only have the set of common properties, but not anything canvas-specific.

function supports_canvas_text() { if (!supports_canvas()) { return false; } var dummy_canvas = document.createElement('canvas'); var context = dummy_canvas.getContext('2d'); return typeof context.fillText == 'function'; }

The function starts by checking for canvas support, using the supports_canvas() function you just saw in the previous section. If your browser doesn’t support the canvas API, it certainly won’t support the canvas text API!

if (!supports_canvas()) { return false; }

Next, you create a dummy <canvas> element and get its drawing context. This is guaranteed to work, because thesupports_canvas() function already checked that the getContext() method exists on all canvas objects.

var dummy_canvas = document.createElement('canvas'); var context = dummy_canvas.getContext('2d');

Finally, you check whether the drawing context has a fillText() function. If it does, the canvas text API is available. Hooray!

return typeof context.fillText == 'function';

Instead of writing this function yourself, you can use Modernizr to detect support for the canvas text API.

↶ check for canvas text support

if (Modernizr.canvastext) { // let's draw some text! } else { // no native canvas text support available :( }

VIDEO

HTML5 defines a new element called <video> for embedding video in your web pages. Embedding video used to be impossible without third-party plugins such as Apple QuickTime® or Adobe Flash®.

audience at the theater
Your browser supports HTML5 video.

The <video> element is designed to be usable without any detection scripts. You can specify multiple video files, and browsers that support HTML5 video will choose one based on what video formats they support. (See “A gentle introduction to video encoding” part 1: container formats and part 2: lossy video codecs to learn about different video formats.)

Browsers that don’t support HTML5 video will ignore the <video> element completely, but you can use this to your advantage and tell them to play video through a third-party plugin instead. Kroc Camen has designed a solution called Video for Everybody! that uses HTML5video where available, but falls back to QuickTime or Flash in older browsers. This solution uses no JavaScript whatsoever, and it works in virtually every browser, including mobile browsers.

If you want to do more with video than plop it on your page and play it, you’ll need to use JavaScript. Checking for video support uses detection technique #2. If your browser supportsHTML5 video, the DOM object it creates to represent a <video> element will have acanPlayType() method. If your browser doesn’t support HTML5 video, the DOM object it creates for a <video> element will have only the set of properties common to all elements. You can check for video support using this function:

function supports_video() { return !!document.createElement('video').canPlayType; }

Instead of writing this function yourself, you can use Modernizr to detect support for HTML5 video.

↶ check for HTML5 video support

if (Modernizr.video) { // let's play some video! } else { // no native video support available :( // maybe check for QuickTime or Flash instead }

In the Video chapter, I’ll explain another solution that uses these detection techniques to convert <video> elements to Flash-based video players, for the benefit of browsers that don’t support HTML5 video.

There is a separate test for detecting which video formats your browser can play, which I will demonstrate next.

VIDEO FORMATS

Video formats are like written languages. An English newspaper may convey the same information as a Spanish newspaper, but if you can only read English, only one of them will be useful to you! To play a video, your browser needs to understand the “language” in which the video was written.

man reading newspaper
Your browser can play both Ogg Theora and H.264 video. Hey, you can play WebM video, too!

The “language” of a video is called a “codec” — this is the algorithm used to encode the video into a stream of bits. There are dozens of codecs in use all over the world. Which one should you use? The unfortunate reality of HTML5 video is that browsers can’t agree on a single codec. However, they seem to have narrowed it down to two. One codec costs money (because of patent licensing), but it works in Safari and on the iPhone. (This one also works in Flash if you use a solution like Video for Everybody!) The other codec is free and works in open source browsers like Chromium and Mozilla Firefox.

Checking for video format support uses detection technique #3. If your browser supportsHTML5 video, the DOM object it creates to represent a <video> element will have acanPlayType() method. This method will tell you whether the browser supports a particular video format.

This function checks for the patent-encumbered format supported by Macs and iPhones.

function supports_h264_baseline_video() { if (!supports_video()) { return false; } var v = document.createElement("video"); return v.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"'); }

The function starts by checking for HTML5 video support, using the supports_video() function you just saw in the previous section. If your browser doesn’t support HTML5 video, it certainly won’t support any video formats!

if (!supports_video()) { return false; }

Then the function creates a dummy <video> element (but doesn’t attach it to the page, so it won’t be visible) and calls thecanPlayType() method. This method is guaranteed to be there, because the supports_video() function just checked for it.

var v = document.createElement("video");

A “video format” is really a combination of different things. In technical terms, you’re asking the browser whether it can play H.264 Baseline video and AAC LC audio in an MPEG-4 container. (I’ll explain what all that means in the Video chapter. You might also be interested in reading A gentle introduction to video encoding.)

return v.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');

The canPlayType() function doesn’t return true or false. In recognition of how complex video formats are, the function returns a string:

  • "probably" if the browser is fairly confident it can play this format
  • "maybe" if the browser thinks it might be able to play this format
  • "" (an empty string) if the browser is certain it can’t play this format

This second function checks for the open video format supported by Mozilla Firefox and other open source browsers. The process is exactly the same; the only difference is the string you pass in to the canPlayType() function. In technical terms, you’re asking the browser whether it can play Theora video and Vorbis audio in an Ogg container.

function supports_ogg_theora_video() { if (!supports_video()) { return false; } var v = document.createElement("video"); return v.canPlayType('video/ogg; codecs="theora, vorbis"'); }

Finally, WebM is a newly open-sourced (and non-patent-encumbered) video codec that will be included in the next version of major browsers, including Chrome, Firefox, and Opera. You can use the same technique to detect support for open WebM video.

function supports_webm_video() { if (!supports_video()) { return false; } var v = document.createElement("video"); return v.canPlayType('video/webm; codecs="vp8, vorbis"'); }

Instead of writing this function yourself, you can use Modernizr (1.5 or later) to detect support for different HTML5 video formats.

↶ check for HTML5 video formats

if (Modernizr.video) { // let's play some video! but what kind? if (Modernizr.video.webm) { // try WebM } else if (Modernizr.video.ogg) { // try Ogg Theora + Vorbis in an Ogg container } else if (Modernizr.video.h264){ // try H.264 video + AAC audio in an MP4 container } }

LOCAL STORAGE

filing cabinet with drawers of different sizes
Your browser supports HTML5 storage.

HTML5 storage provides a way for web sites to store information on your computer and retrieve it later. The concept is similar to cookies, but it’s designed for larger quantities of information. Cookies are limited in size, and your browser sends them back to the web server every time it requests a new page (which takes extra time and precious bandwidth). HTML5 storage stays on your computer, and web sites can access it with JavaScript after the page is loaded.

ASK PROFESSOR MARKUP

☞Q: Is local storage really part of HTML5? Why is it in a separate specification?
A: The short answer is yes, local storage is part of HTML5. The slightly longer answer is that local storage used to be part of the main HTML5 specification, but it was split out into a separate specification because some people in theHTML5 Working Group complained that HTML5 was too big. If that sounds like slicing a pie into more pieces to reduce the total number of calories… well, welcome to the wacky world of standards.

Checking for HTML5 storage support uses detection technique #1. If your browser supports HTML5 storage, there will be alocalStorage property on the global window object. If your browser doesn’t support HTML5 storage, the localStorageproperty will be undefined. Due to an unfortunate bug in older versions of Firefox, this test will raise an exception if cookies are disabled, so the entire test is wrapped in a try..catch statement.

function supports_local_storage() { try { return 'localStorage' in window && window['localStorage'] !== null; } catch(e){ return false; } }

Instead of writing this function yourself, you can use Modernizr (1.1 or later) to detect support for HTML5 local storage.

↶ check for HTML5 local storage

if (Modernizr.localstorage) { // window.localStorage is available! } else { // no native support for local storage :( // maybe try Gears or another third-party solution }

Note that JavaScript is case-sensitive. The Modernizr attribute is called localstorage (all lowercase), but the DOM property is called window.localStorage (mixed case).

ASK PROFESSOR MARKUP

☞Q: How secure is my HTML5 storage database? Can anyone read it?
A: Anyone who has physical access to your computer can probably look at (or even change) your HTML5 storage database. Within your browser, any web site can read and modify its own values, but sites can’t access values stored by other sites. This is called a same-origin restriction.

WEB WORKERS

Your browser supports web workers.

Web Workers provide a standard way for browsers to run JavaScript in the background. With web workers, you can spawn multiple “threads” that all run at the same time, more or less. (Think of how your computer can run multiple applications at the same time, and you’re most of the way there.) These “background threads” can do complex mathematical calculations, make network requests, or access local storage while the main web page responds to the user scrolling, clicking, or typing.

Checking for web workers uses detection technique #1. If your browser supports the Web Worker API, there will be a Workerproperty on the global window object. If your browser doesn’t support the Web Worker API, the Worker property will be undefined.

function supports_web_workers() { return !!window.Worker; }

Instead of writing this function yourself, you can use Modernizr (1.1 or later) to detect support for web workers.

↶ check for web workers

if (Modernizr.webworkers) { // window.Worker is available! } else { // no native support for web workers :( // maybe try Gears or another third-party solution }

Note that JavaScript is case-sensitive. The Modernizr attribute is called webworkers (all lowercase), but the DOM object is called window.Worker (with a capital “W” in “Worker”).

OFFLINE WEB APPLICATIONS

cabin in the woods
Your browser supports offline web applications.

Reading static web pages offline is easy: connect to the Internet, load a web page, disconnect from the Internet, drive to a secluded cabin, and read the web page at your leisure. (To save time, you may wish to skip the step about the cabin.) But what about web applications like Gmail or Google Docs? Thanks to HTML5, anyone (not just Google!) can build a web application that works offline.

Offline web applications start out as online web applications. The first time you visit an offline-enabled web site, the web server tells your browser which files it needs in order to work offline. These files can be anything — HTML, JavaScript, images, even videos. Once your browser downloads all the necessary files, you can revisit the web site even if you’re not connected to the Internet. Your browser will notice that you’re offline and use the files it has already downloaded. When you get back online, any changes you’ve made can be uploaded to the remote web server.

Checking for offline support uses detection technique #1. If your browser supports offline web applications, there will be anapplicationCache property on the global window object. If your browser doesn’t support offline web applications, theapplicationCache property will be undefined. You can check for offline support with the following function:

function supports_offline() { return !!window.applicationCache; }

Instead of writing this function yourself, you can use Modernizr (1.1 or later) to detect support for offline web applications.

↶ check for offline support

if (Modernizr.applicationcache) { // window.applicationCache is available! } else { // no native support for offline :( // maybe try Gears or another third-party solution }

Note that JavaScript is case-sensitive. The Modernizr attribute is called applicationcache (all lowercase), but the DOMobject is called window.applicationCache (mixed case).

GEOLOCATION

Geolocation is the art of figuring out where you are in the world and (optionally) sharing that information with people you trust. There is more than one way to figure out where you are — your IP address, your wireless network connection, which cell tower your phone is talking to, or dedicated GPS hardware that calculates latitude and longitude from information sent by satellites in the sky.

man with a globe for a head
Your browser supports geolocation. Click to look up your location.

ASK PROFESSOR MARKUP

☞Q: Is geolocation part of HTML5? Why are you talking about it?
A: Geolocation support is being added to browsers right now, along with support for new HTML5 features. Strictly speaking, geolocation is being standardized by the Geolocation Working Group, which is separate from theHTML5 Working Group. But I’m going to talk about geolocation in this book anyway, because it’s part of the evolution of the web that’s happening now.

Checking for geolocation support uses detection technique #1. If your browser supports the geolocation API, there will be ageolocation property on the global navigator object. If your browser doesn’t support the geolocation API, the geolocationproperty will be undefined. Here’s how to check for geolocation support:

function supports_geolocation() { return !!navigator.geolocation; }

Instead of writing this function yourself, you can use Modernizr to detect support for the geolocation API.

↶ check for geolocation support

if (Modernizr.geolocation) { // let's find out where you are! } else { // no native geolocation support available :( // maybe try Gears or another third-party solution }

If your browser does not support the geolocation API natively, there is still hope. Gears is an open source browser plugin from Google that works on Windows, Mac, Linux, Windows Mobile, and Android. It provides features for older browsers that do not support all the fancy new stuff we’ve discussed in this chapter. One of the features that Gears provides is a geolocation API. It’s not the same as the navigator.geolocation API, but it serves the same purpose.

There are also device-specific geolocation APIs on older mobile phone platforms, including BlackBerryNokiaPalm, andOMTP BONDI.

The chapter on geolocation will go into excruciating detail about how to use all of these different APIs.

INPUT TYPES

manual typewriter
Your browser supports the following HTML5 input types: searchtel,urlemailnumberrange

You know all about web forms, right? Make a <form>, add a few <input type="text">elements and maybe an <input type="password">, and finish it off with an <input type="submit"> button.

You don’t know the half of it. HTML5 defines over a dozen new input types that you can use in your forms.

  1. <input type="search"> for search boxes
  2. <input type="number"> for spinboxes
  3. <input type="range"> for sliders
  4. <input type="color"> for color pickers
  5. <input type="tel"> for telephone numbers
  6. <input type="url"> for web addresses
  7. <input type="email"> for email addresses
  8. <input type="date"> for calendar date pickers
  9. <input type="month"> for months
  10. <input type="week"> for weeks
  11. <input type="time"> for timestamps
  12. <input type="datetime"> for precise, absolute date+time stamps
  13. <input type="datetime-local"> for local dates and times

Checking for HTML5 input types uses detection technique #4. First, you create a dummy <input> element in memory. The default input type for all <input> elements is "text". This will prove to be vitally important.

var i = document.createElement("input");

Next, set the type attribute on the dummy <input> element to the input type you want to detect.

i.setAttribute("type", "color");

If your browser supports that particular input type, the type property will retain the value you set. If your browser doesn’t support that particular input type, it will ignore the value you set and the type property will still be "text".

return i.type !== "text";

Instead of writing 13 separate functions yourself, you can use Modernizr to detect support for all the new input types defined in HTML5. Modernizr reuses a single <input> element to efficiently detect support for all 13 input types. Then it builds a hash called Modernizr.inputtypes, that contains 13 keys (the HTML5 type attributes) and 13 Boolean values (true if supported, false if not).

↶ check for native date picker

if (!Modernizr.inputtypes.date) { // no native support for <input type="date"> :( // maybe build one yourself with Dojo or jQueryUI }

PLACEHOLDER TEXT

Besides new input typesHTML5 includes several small tweaks to existing forms. One improvement is the ability to set placeholder text in an input field. Placeholder text is displayed inside the input field as long as the field is empty and not focused. As soon you click on (or tab to) the input field, the placeholder text disappears. The chapter on web forms has screenshots if you’re having trouble visualizing it.

Checking for placeholder support uses detection technique #2. If your browser supports placeholder text in input fields, theDOM object it creates to represent an <input> element will have a placeholder property (even if you don’t include aplaceholder attribute in your HTML). If your browser doesn’t support placeholder text, the DOM object it creates for an<input> element will not have a placeholder property.

function supports_input_placeholder() { var i = document.createElement('input'); return 'placeholder' in i; }

Instead of writing this function yourself, you can use Modernizr (1.1 or later) to detect support for placeholder text.

↶ check for placeholder text

if (Modernizr.input.placeholder) { // your placeholder text should already be visible! } else { // no placeholder support :( // fall back to a scripted solution }

FORM AUTOFOCUS

angry guy with arms up
Your browser supports form autofocus.

Web sites can use JavaScript to focus the first input field of a web form automatically. For example, the home page of Google.com will autofocus the input box so you can type your search keywords without having to position the cursor in the search box. While this is convenient for most people, it can be annoying for power users or people with special needs. If you press the space bar expecting to scroll the page, the page will not scroll because the focus is already in a form input field. (It types a space in the field instead of scrolling.) If you focus a different input field while the page is still loading, the site’s autofocus script may “helpfully” move the focus back to the original input field upon completion, disrupting your flow and causing you to type in the wrong place.

Because the autofocusing is done with JavaScript, it can be tricky to handle all of these edge cases, and there is little recourse for people who don’t want a web page to “steal” the focus.

To solve this problem, HTML5 introduces an autofocus attribute on all web form controls. The autofocus attribute does exactly what it says on the tin: it moves the focus to a particular input field. But because it’s just markup instead of a script, the behavior will be consistent across all web sites. Also, browser vendors (or extension authors) can offer users a way to disable the autofocusing behavior.

Checking for autofocus support uses detection technique #2. If your browser supports autofocusing web form controls, theDOM object it creates to represent an <input> element will have an autofocus property (even if you don’t include theautofocus attribute in your HTML). If your browser doesn’t support autofocusing web form controls, the DOM object it creates for an <input> element will not have an autofocus property. You can detect autofocus support with this function:

function supports_input_autofocus() { var i = document.createElement('input'); return 'autofocus' in i; }

Instead of writing this function yourself, you can use Modernizr (1.1 or later) to detect support for autofocused form fields.

↶ check for autofocus support

if (Modernizr.input.autofocus) { // autofocus works! } else { // no autofocus support :( // fall back to a scripted solution }

MICRODATA

alphabetized folders
Your browser does not support the HTML5 microdata API. 😦

Microdata is a standardized way to provide additional semantics in your web pages. For example, you can use microdata to declare that a photograph is available under a specific Creative Commons license. As you’ll see in the distributed extensibility chapter, you can use microdata to mark up an “About Me” page. Browsers, browser extensions, and search engines can convert your HTML5microdata markup into a vCard, a standard format for sharing contact information. You can also define your own microdata vocabularies.

The HTML5 microdata standard includes both HTML markup (primarily for search engines) and a set of DOM functions (primarily for browsers). There’s no harm in including microdata markup in your web pages. It’s nothing more than a few well-placed attributes, and search engines that don’t understand the microdata attributes will just ignore them. But if you need to access or manipulate microdata through the DOM, you’ll need to check whether the browser supports the microdata DOM API.

Checking for HTML5 microdata API support uses detection technique #1. If your browser supports the HTML5 microdata API, there will be a getItems() function on the global document object. If your browser doesn’t support microdata, thegetItems() function will be undefined.

function supports_microdata_api() { return !!document.getItems; }

Modernizr does not yet support checking for the microdata API, so you’ll need to use the function like the one listed above.

FURTHER READING

Specifications and standards:

JavaScript libraries:

  • Modernizr, an HTML5 detection library
  • geo.js, a geolocation API wrapper

Other articles and tutorials:

 

7 tips for team websites

At McGhee Productivity Solutions, we have consultants and employees located around the country. Because we work together on a lot of documents, we need a central location where we can store and edit these documents as well as keep track of our schedules. To work together as efficiently as possible, we use a team website created with Microsoft Windows SharePoint Services. Team sites work great if you have team members working in different locations, or even if your team is all in one office.

In this article, I’m going to give you 7 tips we’ve learned in setting up and using our team website. These tips can help you get up and running productively as quickly as possible with your site.

Note: Windows SharePoint Services is a great, and underused, tool for managing teams and team projects. You can use it to create a team website to track objectives and projects, as well as have a central location for storing and collaborating on documents.

Image of a team website created with Windows SharePoint ServicesExample of a team website created with Windows SharePoint Services.

1. Create folder names that are clear and consistent

Organize site folders by whatever makes the most sense for your team. The key is to be clear and, above all, consistent. For example you could choose to organize:

  • By department
  • By objective
  • Alphabetically
  • By clients
  • By project

We also create a new Document Library folder in SharePoint for each project. We can store all of our files related to a project in a Document Library. This not only helps keep our files organized, but makes it easier if a project is reassigned for the new owner to take ownership of all the associated materials. Learn how to add a new Document Library folder.


2. Develop standards for naming files

Decide as a team how you want to name your files. For example, you can insist that a date be attached to each file, or that the person who created the file put their initials in the file name. Also, you can take advantage of the fact that you can use long file names for files and SharePoint folders. Be sure to publish your naming structure so that everyone on the team knows what it is. Above all, be consistent in reinforcing and using this naming convention. This is critical. We’ve found that if you don’t, your team won’t know how find files and therefore won’t use the site effectively.


3. Keep only the latest versions of files

Develop an archive folder system for keeping previous versions of files for historical or version control needs. We keep only one current version in our “active” folders. This clears up any possible confusion over which version of a document should be used, particularly when your team members download files to their computer to work on while they’re traveling or working out of their office.

If your team members do copy files onto their computers, you need to take extra precautions to ensure you only have the most current versions of their files on the team website. If team members keep versions of files on their computer, they should change the file name. That way, if they upload the file at a later date, they will not overwrite something on the team website that might have been edited in the meantime.


4. Give clear ownership of each section of the team website

Give each folder a single owner who can add files to it. We find that this ensures the integrity of naming and file structures within each section of the team website. Multiple people may edit documents in various folders, but we make sure no one else uploads new documents or creates new folders inside a folder owned by someone else.


5. Check out and check in files

You will probably have a number of files (like sales data) that are accessed and edited by several team members. While SharePoint won’t allow multiple people to save an open file, it is possible for a person to open a file while someone else is editing it. Unless the file is checked out, you run the risk of more than one person working on the same file. One or more people may end up doing work that can’t be properly saved. And if a user doesn’t check the file back in, then others can’t access it. Learn how to:

Image of how to check out a fileMake sure you check out files on your team website before working on them.


6. Clearly describe folder contents

As people on the team change, they will need to know what they can expect to find in different Document Library folders. Because we include a clear description of each folder, the new team member knows what’s in each folder and can find the documents they need to get up to speed a lot faster. This has been really useful to us when an account grows large enough that we add another consultant to the team. We also modify the descriptions when we complete a project. We designate the library as containing archive information rather than active information.

Image of a Document LibraryClearly describe each folder in your Document Library.

To put in a detailed description of a Document Library:

  1. Click on the Document Library you want to edit.
  2. In the Document Library you want to edit, in the left navigation, click Modify Settings and Columns.
  3. On the Customize page, in the General Settings section, click Change General Settings.
  4. This takes you to the Document Library Settings page, In the Name and Description section, type in the description of the folder. Click OK.

7. Link to files in SharePoint folders

When you’re working on a project, it’s easy to just insert a file from the team website into an email. By sending out different versions of the same file, however, you could end up with multiple versions of the same document. It’s far more reliable to just insert a link to the document in your email. You can also put links to SharePoint documents into a task in Microsoft Office Outlook, or into an appointment on your calendar.

If you store multiple copies of a file on your team website, it’s also easy for one copy of the file to get modified and leave the others out of date. Instead, we make sure we only have one version of a document and link to it from other places when necessary.

To put a link to file on your team website into any Microsoft Office document:

  1. Locate the document you want to create a link for. Put your cursor over the document name until the file name turns red.
  2. Right-click on the red file name and in the drop-down menu and click Copy Shortcut.
  3. With your mouse cursor in the body of your task, appointment, contact, documents folder, or in another file, right-click and click Paste. This will paste the link. When you click on the link, it will open the actual document.
Image of a how to copy a shortcut in Windows SharePoint ServicesPut links to documents on your team website rather then putting different versions in multiple locations.

To put a link to file on your team website into another part of the website:

  1. Locate the document you want to create a link for. Put your cursor over the document name until the file name turns red.
  2. Right-click on the red file name and in the drop-down menu and click Copy Shortcut.
  3. Navigate to the folder you want to include the link in. Click New Document. SharePoint will open a new document called “template.htm” in Microsoft Word.
  4. Paste the shortcut into the new document. Select all of the text and right click on it.
  5. Click Hyperlink… and type in the text you want in the Text to display box (for example, “Click here to see the final version of this presentation.”) Click OK.
  6. Save the file. When anyone opens this file, clicking the link will take them to the current version of the referenced file.

I hope sharing some of the lessons we’ve learned at McGhee Productivity Solutions will help you get a head start on your own team website.

 

PHP Template with Smarty(.tpl)

Why would I use Smarty (when PHP is a template engine)?

Some might argue that Smarty does what PHP can do already: separate the presentation from business logic. The PHP programming language is great for code development but when mixed with HTML, the syntax of PHP statements can be a mess to manage. Smarty makes up for this by insulating PHP from the presentation with a much simpler tag-based syntax. The tags reveal application content, enforcing a clean separation from PHP (application) code. No PHP knowledge is required to manage Smarty templates.

The importance of this separation is situational. It is commonly more important to web designers than it is to PHP developers. Therefore, Smarty is commonly a good fit when the roles of developers and designers are separated. There is no right or wrong answer: every development team has their own preferences for managing code and templates. Aside from a clean tag-based syntax, Smarty also offers a wide variety of tools to manage presentation: granular data caching, template inheritance and functional sandboxing to name a few. Business requirements and the PHP code Smarty is being used with will play a large role in determining if Smarty is a good fit.

In cases where efficient template management is crucial, or the case where web designers (not PHP developers) are managing templates, the strengths of the tag-based template syntax are quickly realized. If the project size scales to hundreds or thousands of templates, template inheritance keeps template maintenance streamlined. What little Smarty adds technically (a tag-based syntax + 1-time compile step) is easily overcome by the time saved with template maintenance.

Smarty is clearly not meant for every project. It is just one solution for managing the presentation of your PHP applications. Your business requirements along with your development team preferences will largely decide of Smarty is a good fit. Be sure to read All about Smarty, Use Cases and Work Flow, Template Inheritance and Syntax Comparison. And of course, install Smarty and give it a try.

Template Syntax: Smarty vs PHP

The PHP programming language is great for code development, but many will argue that embedding its terse statement syntax into HTML can be difficult to manage. Smarty makes up for this by insulating PHP from the presentation with a much simpler tag-based syntax. The tags reveal application content within the presentation in a clean, intuitive manner. No PHP knowledge is required to manage Smarty templates.

To demonstrate, let’s compare PHP and Smarty syntax. We’ll start with a simple variable, using PHP’s short-tag syntax.
PHP

<?=$foo?>

Smarty

 {$foo}

Note that the PHP syntax uses 5 punctuation characters to display a simple variable: <?=?>, whereas Smarty uses 2: {}. (We ignore the $ since it is always present in both syntaxes.) Now lets compare array access:
PHP

<?=$foo['bar']?>

Smarty

{$foo.bar}

PHP uses 9 punctuation chars, and Smarty uses 3. Even with this simple example, you can begin to see how the syntax noise is greatly reduced by Smarty. Moving on, let’s try a foreach loop:
PHP

<?php foreach($foo as $bar): ?>
 ...
 <?php endforeach; ?>

Smarty

{foreach $foo as $bar}
 ...
{/foreach}

PHP uses 18 punctuation chars, and Smarty uses only 5. Now let’s try some real-world use, mixing things with HTML tags:
PHP

<?php if(!empty($foo)): ?>
 <?php foreach($foo as $bar): ?>
 <a href="<?=$bar['zig']?>"><?=$bar['zag']?></a>
 <a href="<?=$bar['zig2']?>"><?=$bar['zag2']?></a>
 <a href="<?=$bar['zig3']?>"><?=$bar['zag3']?></a>
 <?php endforeach; ?>
<?php else: ?>

There were no rows found.

<?php endif; ?>
 Smarty
 {foreach $foo as $bar}
 <a href="{$bar.zig}">{$bar.zag}</a>
 <a href="{$bar.zig2}">{$bar.zag2}</a>
 <a href="{$bar.zig3}">{$bar.zag3}</a>
{foreachelse}</pre>
 There were no rows found.
{/foreach}

In the short example above, Smarty saved 110 characters, or a 36% syntax reduction. Also notice that Smarty takes care of boilerplate functions wherever it can, such as the empty() test in the above example. Smarty cleans up the syntax of templates, making them less fragile.
PHP short-tags

Notice we have been using the PHP short-tag syntax <?=$foo?> for variable output. This is used in PHP as as shortcut to the longer syntax of <?php echo $foo; ?>. This helps shorten things up bit, but you still don’t gain much in readability. Many PHP devs will tell you to avoid short-tags anyways, as this defeats cross-system compatible code since short-tags are optional. Lets compare the long syntax to a Smarty variable:
PHP

<?php echo $foo; ?>

Smarty

{$foo}

Even with this short example, you can see a 13 character savings (69% shorter) to display the same thing. Now let’s see this mixed in with some HTML:
PHP

 <a href="<?php echo $bar['zig']; ?>"><?php echo $bar['zag']; ?></a>
 <a href="<?php echo $bar['zig2']; ?>"><?php echo $bar['zag2']; ?></a>
<a href="<?php echo $bar['zig3']; ?>"><?php echo $bar['zag3']; ?></a>

Smarty

 <a href="{$bar.zig}">{$bar.zag}</a>
 <a href="{$bar.zig2}">{$bar.zag2}</a>
<a href="{$bar.zig3}">{$bar.zag3}</a>

Delimiter Confusion

Another issue with PHP tags is that they share the <> characters of HTML tags. In the application code this isn’t an issue, but mixed with HTML, <?php ?> tags are a maddening process to tell them apart from the HTML tags. This also blurs the line between application and presentation separation since any PHP logic can be injected into a template. This is where a simple {tag} syntax is a huge welcome. Smarty keeps the presentation short and concise, well-defined, less error prone and easy to maintain.
Simplified Logic

Smarty features simplified, english-reading logic statements. The following example displays the odd numbers of 1-20 (1,3,5,7,…):

PHP

 <?php for($x=0; $x<20; $x+=2): ?>
 <php echo $x+1; ?>
<?php endfor; ?>

Smarty

 {for $x = 1 to 20 step 2}
 {$x}
{/for}

Which is easier to understand? How about for the non-developer types?

The following example loops over the $foo array and prints the value in a table cell. Every 4th row it prints </tr><tr> to start a new table row:
PHP

 <?php $counter=0; ?>
 <?php foreach($foo as $bar): ?>
 <?php if(($counter+1) % 4 == 0): ?>
 </tr><tr>
 <?php endif; ?>
 <td><?php echo $bar; ?></td>
 <?php $counter++; ?>
<?php endforeach; ?>

Smarty

 {foreach $foo as $bar}
 {if $bar@iteration is div by 4}
 </tr><tr>
 {/if}
 <td>{$bar}</td>
{/foreach}

The next example lower-cases and html-escapes a variable:
PHP

<?php echo htmlspecialchars(strtolower($foo),ENT_QUOTES,'UTF-8'); ?>

Smarty (notice the natural left-to-right statement flow):
Smarty

{$foo|lower|escape}

lower and escape are two of many built-in plugins that come with Smarty. They contain powerful features aimed specifically at presentational output. Do you want to javascript-escape the variable instead? One simple parameter:
Smarty

{$foo|lower|escape:javascript}

Which of the above do you think a designer would rather follow? Short, concise syntax is key to fast deployment and easy maintenance.

These are just a few examples of how Smarty saves you time managing templates, insulates templates from PHP code, and makes template maintenance easy, even for the completely inexperienced user. See also All about Smarty, Use Cases and Work Flow, Template Inheritance and Why use Smarty.

Template Inheritance

Template inheritance is an approach to managing templates that resembles object-oriented programming techniques. Instead of the traditional use of {include …} tags to manage parts of templates, you can inherit the contents of one template to another (like extending a class) and change blocks of content therein (like overriding methods of a class.) This keeps template management minimal and efficient, since each template only contains the differences from the template it extends.
A Use Case Demonstration

The challenge: Let’s say we are creating an HTML page, and it requires some custom Javascript/CSS files loaded within the <head></head> of the document. The problem is that this is defined in the header.tpl, which was included further up the page. There are many ways to address this, but they can get quite messy. Let’s make this task an easy one, with Template Inheritance, new to Smarty 3.

Before template inheritance, we were stuck with using {include …} tags to share content such as headers and footers. Here is an example:
Example Without Inheritance

 header.tpl
 <html>
 <head>
 <title>{$title|default:"Default Page Title"}</title>
 </head>
 <body>
 footer.tpl
 </body>
 </html>
 mypage.tpl
 {include file="header.tpl" title="My Page Title"}
 My HTML Page Body goes here
 {include file="footer.tpl"}
 output of mypage.tpl
 <html>
 <head>
 <title>My Page Title</title>
 </head>
 <body>
 My HTML Page Body goes here
 </body>
 </html>

Now let’s rewrite this with template inheritance:
Example With Inheritance

 layout.tpl
 <html>
 <head>
 <title>{block name=title}Default Page Title{/block}</title>
 </head>
 <body>
 {block name=body}{/block}
 </body>
 </html>
 mypage.tpl
 {extends file="layout.tpl"}
 {block name=title}My Page Title{/block}
 {block name=body}My HTML Page Body goes here{/block}
 output of mypage.tpl
 <html>
 <head>
 <title>My Page Title</title>
 </head>
 <body>
 My HTML Page Body goes here
 </body>
 </html>

Instead of managing our page layout in several files (header.tpl, footer.tpl, etc.), we now manage it in one cohesive template (layout.tpl), and define the changeable blocks of content with {block …} tags. Now you can simply extend the layout.tpl (which basically copies it) and then customize any of the defined block elements. You can have any number of child templates chained together, thus the concept of inheritance.

So back to our initial challenge, how do we address the need to have custom Javascripts/CSS loaded in the header? Simply add a new block to the layout.tpl, and customize it in the child template:

 layout.tpl
 <html>
 <head>
 <title>{block name=title}Default Page Title{/block}</title>
 {block name=head}{/block}
 </head>
 <body>
 {block name=body}{/block}
 </body>
 </html>
 mypage.tpl
 {extends file="layout.tpl"}
 {block name=title}My Page Title{/block}
 {block name=head}
 <link href="/css/mypage.css" rel="stylesheet" type="text/css"/>
 <script src="/js/mypage.js"></script>
 {/block}
 {block name=body}My HTML Page Body goes here{/block}
 output of mypage.tpl
 <html>
 <head>
 <title>My Page Title</title>
 <link href="/css/mypage.css" rel="stylesheet" type="text/css"/>
 <script src="/js/mypage.js"></script>
 </head>
 <body>
 My HTML Page Body goes here
 </body>
 </html>

As you can see, we can now easily customize header content from the child template. This is the basics of template inheritance. It cleans up template management, and makes tough problems trivial!

Best Practices

Although Smarty helps facilitate the separation of business logic (PHP) from presentation, that does not mean it prevents poor implementation. No different than any other software, Smarty has a learning curve. Smarty does not guarantee good application design or proper separation of presentation, this still needs to be addressed by a competent developer and web designer. We’ll cover some of the more common pitfalls and how to avoid them.

Note: With Smarty we typically refer to the PHP developer and the template designer as separate roles. Although this could be the same person in real life, it is good to think of them as separate roles so you can clearly understand what belongs in PHP and what belongs in templates.

Now lets get to the first problem: embedding PHP in templates.
1. Do not imbed PHP!

This is by far the biggest mistake with Smarty templates. When Smarty was first developed, the {php} tag was provided as a sort of “last resort” way of solving a problem. Experience has revealed that directly embedding PHP is not only unnecessary, it creates more problems than it solves. The {php} tag is strongly discouraged, and is now deprecated in Smarty 3.

Despite the discouragement, lazy developers continue to fall on the {php} crutch, as this may seem (at first glance) to be the quickest path to implementation. However, this approach just leads to more problems. The correct approach is to implement a plugin and do the PHP logic outside of the template.

First lets look at how not to use Smarty.
Example problem: solved the wrong way

Let’s say we have this existing PHP function that grabs the current weather forecast and displays it in an HTML table.
PHP

 function get_forecast($zipcode) {
 // some weather class we use to do the fetching
 include_once('weather.php');
 // get the forecast from the weather station
 $forecast = Weather::forecast($zipcode);
 // now mark up and return
 $output = "<table>";
 $output .= "<tr><td>Temp:</td><td>".$forecast['temp']."</td></tr>";
 $output .="</table>";
 return $output;
 }

So now our esteemed PHP developer wants to implement this in a Smarty template. Easy, right? We just throw it in with {php} tags:
Smarty

{php}echo get_forecast($zipcode);{/php}

So we basically “escape” the template for a moment into PHP code and run the function. Uh oh, we have a problem. Our $zipcode variable is a template variable, and it won’t “just work” in a {php} block. So we have to get that from the Smarty object. Have no fear, with a little more code we can access that:
Smarty

{php}echo get_forecast($this->getTemplateVars('zipcode'));{/php}

Oops, we have another problem. Our PHP function get_forecast() is not available. We must first include this file. Let’s say we have a PHP constant MY_APP defined and we know the filepath relative to that. So we’ll throw in an include() statement to include the file:
Smarty

 {php}include(dirname(MY_APP).DIRECTORY_SEPARATOR.'forecast.php');
 echo get_forecast($this->getTemplateVars('zipcode'));{/php}

Although this technically works, we just did exactly what Smarty was intended to avoid: We now have a syntactical mess, and we have business logic in our template (PHP constructs and logic that have nothing to do with the presentation.)

Let’s say the template designer looks at the output and decides that we don’t want the weather in an HTML table. Instead, we want a <div> container with some stylesheet markup. So the designer heads off to the template to change it. Finding this in the template is not a welcome sight. Since there is no way to manage the markup from the template, the designer needs to either inform the PHP developer what to change, or locate and change the PHP code themselves (oops, there goes the separation.) This is probably not the best implementation.
Example problem: solved the right way

Now let’s solve the same problem by making a simple template plugin. By implementing a plugin we will keep business logic out of the template, and move all presentational elements into the template, establishing the correct separation. We can either create a new plugin file in the Smarty plugins directory, or we can make a PHP function (or class method) somewhere in our application code and register it with Smarty manually. Let’s go with the plugin file method. Here is what our plugin file will look like:
PHP

 <?php
 /*
 * Smarty plugin
 * -------------------------------------------------------------
 * File:     function.get_forecast.php
 * Type:     function
 * Name:     get_forecast
 * Purpose:  gets the weather forecast
 * -------------------------------------------------------------
 */
 function smarty_function_get_forecast($params, $smarty)
 {
 // some weather class we use to do the fetching
 include_once('weather.php');
 // get the forecast from the weather station
 $forecast = Weather::forecast($params['zipcode']);
 // now mark up and return
 $output = "<table>";
 $output .= "<tr><td>Temp:</td><td>".$forecast['temp']."</td></tr>";
 $output .="</table>";
 return $output;
 }
 ?>

And now let’s implement this in our template:
Smarty

{get_forecast zipcode=$zipcode}

Now this looks a whole lot better. The template now contains something very easy to understand. We are not quite finished: remember that we want to be able to handle the presentation on the template side, so we need to move the markup into the template. This will also simplify our plugin logic, as it no longer has to deal with presentation (as it should be.) Let’s make those changes:
PHP

 <?php
 /*
 * Smarty plugin
 * -------------------------------------------------------------
 * File:     function.get_forecast.php
 * Type:     function
 * Name:     get_forecast
 * Purpose:  gets the weather forecast
 * -------------------------------------------------------------
 */
 function smarty_function_get_forecast($params, $smarty)
 {
 include_once('weather.php');
 // get the forecast from the weather station
 $forecast = Weather::forecast($params['zipcode']);
 // assign forecast data directly to given template var
 $smarty->assign($params['assign'],$forecast);
 }
 ?>

And in the template:
Smarty

 {get_forecast zipcode=$zipcode assign="forecast"}
 <div>Temp: {$forecast.temp}</div>

We’ve moved the business logic (PHP) into the plugin, and we moved presentation (HTML/CSS) to the template. We’re done! Now compare this solution to the previous example, and you can probably recognize what a programmer and template designer would rather work with. This syntax is very easy to understand and maintain.

Of course, there are other ways to approach this problem. You could simply assign $forecast to the template from the PHP code, foregoing the need to create a {get_forecast} plugin altogether:
PHP

 $smarty->assign('forecast',get_forecast($zipcode));
 Smarty
 <div>Temp: {$forecast.temp}</div>

That works too. The first approach allows us to independently fetch the forecast from any template. You can decide for yourself the best way to implement it.
2. Keep PHP constructs separate!

Another common pitfall is embedding PHP constructs (such as objects/classes/functions) into a template when it is better to keep them separate. Let’s take an example of editing an article. We display an article on the page and if the current user is an editor, we want to show the edit buttons too. In our PHP logic we have a $roles object we use to check the user’s role:
PHP

if($roles->isEditor($_SESSION['user_id'])) { /* do something */ }

The first thing a developer may be tempted to do is assign the $roles object directly to the template and use it as such:
Smarty

 {if $roles->isEditor($smarty.session.user_id)}
 ... show edit buttons here ...
 {/if}

This introduces several problems. First, we are creating a tight coupling of the underlying PHP object structure to the template, e.g, we can no longer make changes to the application without directly affecting the template. Second, we are introducing application logic into the template (accessing user roles.) Third, this complicates the template syntax, and you expose PHP class/methods/parameters that may not have anything to do with presentation. The template designer does not need to deal with user roles, they only need to know whether or not to show the edit buttons.

Here is an approach to keep things separate. In our PHP logic, we will assign a simple flag to Smarty:
PHP

 // assign a flag for Smarty
 $smarty->assign('show_edit_buttons',
 $roles->isEditor($_SESSION['user_id']));

And in our template, we use the flag:
Smarty

 {if $show_edit_buttons}
 ... show edit buttons here ...
 {/if}

Now our template focuses purely on the presentation. In some cases a flag name like $is_editor may be more appropriate, depending on what contexts it is used. But you get the basic idea. Keep the business logic out, and focus on presentation.

Now that said, embedding PHP constructs into templates is a fine line. There may be instances where this works better for your implementation. You have the ability to embed them, just be sure you understand the implications.
3. Keep business logic separate!

It may be tempting to create template functions that do neat things, but remember to keep them focused on presentation and not business logic. Here is a prime example of writing a template function that breaks the separation:
Smarty

 {sql statement="select * from categories order by catname limit=$start,$limit" assign="result"}
 {result.catname}
 {/sql}

There are several problems here. First, direct SQL statements are business logic. The designer should not need to know anything about SQL or where content comes from, let alone control exactly how this content is retrieved. Second, we open a potential security hole with SQL statements in the templates. The designer could easily break the SQL statement, the parameters could be wrong, or (depending on where your parameters come from) malicious injection attacks could happen. Here is a much better approach to the above example, using a plugin that cleanly separates the business logic from presentation:
Smarty

 {get_categories limit=10 assign="result"}
 {$result.catname}
 {/get_categories}

In our get_categories block plugin we handle the parameter cleansing and SQL access, and the template focuses purely on presentation. You could also assign $result directly to the template from PHP (probably the more common approach), but this design allows us to retrieve the categories arbitrarily from any template. Use your own judgement for your implementation.
4. How to identify business vs presentation logic

Business logic is normally any logic that does not deal directly with the presentation, or display of content. For instance, regular expressions embedded in the template are normally better handled in PHP, either in a plugin or before content is assigned. Although Smarty ships with a regex_replace modifier, it is normally better to do this in PHP.

Here is an example of using regex_replace. We want to make all emails into links in the description text:
Smarty- business logic in template (bad!)

{$description|regex_replace:"!(\w+@\w+)!":'<a href="mailto:$1">$1/a>'}

It is not immediately obvious what is going on here, unless you are a regex guru. This terse template syntax is a clue that we have business logic in the template. A better approach is to use a custom plugin (modifier):
PHP

 <?php
 /*
 * Smarty plugin
 * -------------------------------------------------------------
 * File:     modifier.link_emails.php
 * Type:     modifier
 * Name:     link_emails
 * Purpose:  make emails in text into HTML links
 * -------------------------------------------------------------
 */
 function smarty_modifier_link_emails($string)
 {
 return preg_replace('!(\w+@\w+)!','<a href="mailto:$1">$1</a>',$string);
 }
 ?>

Smarty

{$description|link_emails}

Now it is perfectly clear what is happening, regardless of the template designer’s knowledge of regular expressions.

Recall that we keep the template designer and application developer roles separate. The purpose of this is to define a separation between presentation and business logic. If the person editing the templates is quite familiar with PHP, that doesn’t mean these rules should not apply. The purpose is to keep the business logic out of the template. This will go a long ways toward fast development, concise template syntax and easy maintenance.

When making decisions where to put logic (in templates or in PHP), try to keep the templates focused on presentation. If you find yourself struggling with template syntax, making syntax too complicated, or trying to access PHP from the templates, there is usually a better approach. Think about the separation, and how to implement it in a way that keeps template syntax minimal and focused on presentation.

jQuery Templates – XHTML Validation

Maybe you have already tried, and I don’t know what are your results but here is my opinion regarding this.

By default, Visual Studio.NET adds the xhtml1-transitional.dtd schema

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”&gt;

So, if you try to validate your page which has jQuery Templates against this schema, your page won’t be XHTML valid. Why?

It’s because when creating templates, we use HTML tags inside <script> … </script> block. Yes, I know that the script block has type=”text/html” but it’s not supported in this schema, thus it’s not valid.

Let’s try validate the following code

Code

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”&gt;

<html xmlns=”http://www.w3.org/1999/xhtml” &gt;
<head>
<title>jQuery Templates :: XHTML Validation</title>
<script src=”http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.4.4.min.js” type=”text/javascript”></script&gt;
<script src=”http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.js” type=”text/javascript”></script&gt;

<script language=”javascript” type=”text/javascript”>
$(function () {
var attendees = [
{ Name: “Hajan”, Surname: “Selmani”, speaker: true, phones: [070555555, 071888999, 071222333] },
{ Name: “Denis”, Surname: “Manski”, phones: [070555555, 071222333] }
];

$(“#myTemplate”).tmpl(attendees).appendTo(“#attendeesList”);
});
</script>

<script id=”myTemplate” type=”text/html”>
<li>
${Name} ${Surname}
{{if speaker}}
(<font color=”red”>speaks</font>)
{{else}}
(attendee)
{{/if}}
</li>
</script>

</head>
<body>
<ol id=”attendeesList”></ol>
</body>
</html>

To validate it, go to http://validator.w3.org/#validate_by_input and copy paste the code rendered on client-side browser (it’s almost the same, only the template is rendered inside OL so LI tags are created for each item).

Press CHECK and you will get:

Result: 1 Errors, 2 warning(s)

The error message says:

Validation Output: 1 Error

Error Line 21, Column 13: document type does not allow element “li” here

         <li>

Yes, the <li> HTML element is not allowed inside the <script>, so how to make it valid?


1st SOLUTION: Using <![CDATA][…]]>

The first thing that came in my mind was the CDATA. So, by wrapping any HTML tag which is in script blog, inside <![CDATA[ …….. ]]> it will make our code valid. However, the problem is that the template won’t render since the template tags {} cannot get evaluated if they are inside CDATA.

Ok, lets try with another approach.
2nd SOLUTION: HTML5 validation

Well, if we just remove the strikethrough part bellow of the !DOPCTYPE

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&#8221;>

our template is going to be checked as HTML5 and will be valid.

Ok, there is another approach I’ve also tried:
3rd SOLUTION: Separate the template to an external file

We can separate the template to external file. I didn’t show how to do this previously, so here is the example.

1. Add HTML file with name Template.html in your ASPX website.

2. Place your defined template there without <script> tag

Content inside Template.html

<li>
${Name} ${Surname}
{{if speaker}}
(<font color=”red”>speaks</font>)
{{else}}
(attendee)
{{/if}}
</li>

3. Call the HTML file using $.get() jQuery ajax method and render the template with data using $.tmpl() function.

$.get(“/Templates/Template.html”, function (template) {
$.tmpl(template, attendees).appendTo(“#attendeesList”);
});

So the complete code is:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”&gt;

<html xmlns=”http://www.w3.org/1999/xhtml” &gt;
<head>
<title>jQuery Templates :: XHTML Validation</title>
<script src=”http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.4.4.min.js” type=”text/javascript”></script&gt;
<script src=”http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.js” type=”text/javascript”></script&gt;

<script language=”javascript” type=”text/javascript”>
$(function () {
var attendees = [
{ Name: “Hajan”, Surname: “Selmani”, speaker: true, phones: [070555555, 071888999, 071222333] },
{ Name: “Denis”, Surname: “Manski”, phones: [070555555, 071222333] }
];

$.get(“/Templates/Template.html”, function (template) {
$.tmpl(template, attendees).appendTo(“#attendeesList”);
});
});
</script>

</head>
<body>
<ol id=”attendeesList”></ol>
</body>
</html>

This document was successfully checked as XHTML 1.0 Transitional!

Result: Passed


UPDATE

SOLUTION 4: Separate the template to an external file and place it inside JavaScript variable

I was pretty sure that someone will mention the <script src=”file-name” /> to load the template. Well, if it’s on the normal HTML-like format we write it, it won’t work

Of course, if you put the template in JS variable and place it in separate JS (or HTML) file, it will work prefectly.

So, we can write the template on the following way:

/Templates/Template.js file

var myTemplate =
“<li>” +
“${Name} ${Surname}” +
“{{if speaker}}” +
“(<font color=\”red\”>speaks</font>)” +
“{{else}}” +
“(attendee)” +
“{{/if}}” +
“</li>”;

So, you can reference this file in your page using <script src=”http://localhost/Templates/Template.js&#8221; type=”text/javascript”></script>

And, to make this work, here is the jQuery code

<script language=”javascript” type=”text/javascript”>
$(function () {
var attendees = [
{ Name: “Hajan”, Surname: “Selmani”, speaker: true, phones: [070555555, 071888999, 071222333] },
{ Name: “Denis”, Surname: “Manski”, phones: [070555555, 071222333] }
];
//myTemplate is the name of the variable
$.template(“myExternalTemplate”, myTemplate); // Compile the template as named template so we can reuse it
$.tmpl(“myExternalTemplate”, attendees).appendTo(“#attendeesList”); //append it to HTML
});
</script>

Instead of using AJAX call, we have replaced this code with the two lines which contains //COMENTS.

This way solves the problem we have. Of course, this is beta version plugin and I do expect in the future to have some functionality to load external templates much easier.

If you have any additional methods for XHTML validation, you can share it :).