Monthly Archives: September 2013

Create custom tables with WebGrid

ASP.NET MVC has made the task of creating an interactive table straightforward. Michael Schmalz demonstrates a neat technique for styling it any way you wish

If you are building data tables with paging and sorting from scratch when using ASP.NET MVC, you are missing out on one of the easiest-to-use helpers. WebGrid gives you built-in support for clickable headers for sorting and paging in the footer. But there is a lot of misinformation about what you can and cannot do with the WebGrid.

This article covers creating a fully formatted table with a strongly typed view using the WebGrid helper. The full code for this project includes views that show the WebGrid with no formatting, with footer CSS formatting alone, with table formatting, and our main topic – customising the footer with paging and other information.

The data for this project is an enumerable list created in the controller; I would typically use SQL Server and access the data with Entity Framework. I created the data in the controller to keep it short enough for an article. You will be using a data model in this example, like you would with Entity Framework, but you won’t be storing or accessing the data in a database.

If you want to see what is going on with your page while editing, you can press F12 in Internet Explorer and see how the styles are being applied

Understanding the model

The WebGrid helper returns a regular HTML table. You can apply CSS styles to format it as you would any other table. First, you’ll build the grid and see how to format the columns, rows and footer. Next, you’ll see how to customise the paging footer with extra information, via a nice technique I’ve developed. For this example, you will use data in a model called Transaction – it’s simply: public class Transaction

public class Transaction
  { public int TransactionID { get; set; }
    public DateTime TranDate { get; set; }
    public string Description { get; set; }
    public int Units { get; set; }
    public double UnitPrice { get; set; }
    public double Total { get; set; } }

This should be in the Models folder in the supporting download for the tutorial with the name Transaction.cs. In the controller, you will populate this model with the following code (to save space, this is just a sample of three records):

public IEnumerable<Transaction> GetList()
{var tr = new List<Transaction>() {
new Transaction { TransactionID = 1, Description = “Large Latte”,
TranDate = System.DateTime.Parse(“6/1/2012”), Units = 5, UnitPrice = 3.5 },
new Transaction { TransactionID = 2, Description = “Skinny Latte”,
TranDate = System.DateTime.Parse(“6/5/2012”), Units = 7, UnitPrice = 3.25 },
………
new Transaction { TransactionID = 14, Description = “Medium Coffee of the Day”, TranDate = System.DateTime.Parse(“9/13/2012”), Units = 58, UnitPrice = 2.15 }};
  return tr;}

In the full project code, I call this method from all of the views to populate the data to send to the view. Also, you may have noticed that the model has a Total field that is not being populated; I decided not to populate that in the controller so that I can show you how to have a calculated field in a WebGrid. In the full project code I have two where it is calculated in the controller.

The controller code for the view is only a few lines, because the paging and sorting is handled by the WebGrid helper. As the view includes a form to filter the data, there are two ActionResult procedures in the controller for this view.

The HttpPost ActionResult just does a redirect, and includes the parameters for the date range. If you did it this way, the date range would be embedded in the clickable headers automatically by the WebGrid helper; if you just returned the filtered view, when you clicked the header it would remove the filter.

public ActionResult Grid(DateTime? Begin, DateTime? End)
  {var tr = GetList();
    if (Begin != null && End != null)
    { DateTime begindt = Convert.ToDateTime(Begin);
      DateTime enddt = Convert.ToDateTime(End).AddDays(1);
      var tr2 = tr.Where(a => a.TranDate >= begindt && a.TranDate < enddt);
      return View(tr2);}
    return View(tr);}
  [HttpPost]
public ActionResult Grid(FormCollection fc)
  {return RedirectToAction(“Grid”, new { Begin = fc[“begin”], End = fc[“end”] });}

The first ActionResult has two optional parameters (designated by the question mark after the data type) and it works fairly straightforwardly. First, the list is retrieved with the code shown earlier.

If both the Begin and End parameters are not null, they are converted to work with the query. Since the DateTime field can include the time portion, the end date is going to have one day added and the filter is set for less than the End parameter plus one day.

The filtering is being done using lambda expressions, which are very useful when working with data.

Our unformatted WebGrid, showing the default footer style. Over the course of this tutorial, we will set up a custom style for the footer

The next ActionResult takes the FormCollection and the Begin and End parameters are returned to the main action. If you compare this to trying to put all of the paging and sorting in the controller, you will see that this is very compact code. Now you are ready to work on the view. The first line of code on the view sets it up to be a strongly-typed view. That reads:

@model IEnumerable<WebGridExample.Models.Transaction>

This means that the view expects the controller to pass an enumerable collection of the model Transaction to the view. This is the data that is being passed to the WebGrid helper. The next section of code is the style block that includes the CSS classes that you will be using in the WebGrid.

<style type=”text/css”>
.tranlist tr:nth-child(odd) { background-colour: #afc1d9; }
.tranlist tr:nth-child(even) { background-colour: white; }
.tranlist th { background-colour: Black; colour: White; }
.tranlist a { colour: White; }
.smallcolumn {min-width:20px;}
.medcolumn {min-width: 50px;}.bigcolumn{min-width:100px; }
.linkcolumn { min-width: 90px; text-align: center; } .linkcolumn a { colour: Black;
} .linkcolumn a:hover { colour: Blue; }
.footstuff { background-colour: White; colour: Red; }
.footstuff a:visited { colour: Blue; } .footstuff a { colour: Blue;}
.footstuff td { background-colour: White; border-colour: White; }
.headerstyle th {text-transform: capitalize; text-align: center;}
</style>

These styles are doing the following: setting different background colours for alternating rows, setting the table header black with white text, setting minimum widths and styles for certain columns, and setting the style for the footer. The actual styles here aren’t that important; what is important is how you tell the WebGrid how to use those styles, which we’ll look at soon.

Creating a WebGrid

The next section of code creates a WebGrid with the model and sets up page variables to hold the values from the query string if they exist.

@{ var grid = new WebGrid(Model, defaultSort: “TransactionID”, rowsPerPage: 5);
  if (Request.QueryString[grid.SortDirectionFieldName].IsEmpty())
  {grid.SortDirection = SortDirection.Descending;}
  DateTime beg = System.DateTime.Now; DateTime end = System.DateTime.
  Now;
  if (Model.Count() != 0) {beg = Model.Min(a => a.TranDate);
    end = Model.Max(b => b.TranDate);} }

This just creates the grid object, passes in the data from the model, sets the sort field to TransactionID, and sets up the paging for five rows per page. You need to call a different method to return HTML to the browser. The other code sets an initial sort direction of descending to show the newest transactions first, and gets the dates for the newest and oldest transactions. If you have more than one grid on the page, use grid.SortDirectionFieldName instead of the default of sortdir so that the field name can be changed. The next section of code creates the form so that you can implement filtering by date range.

<form id=”daterange”>
Begin <input name=”begin” id=”begin” type=”date” value=”@beg.
ToShortDateString()” />
End <input name=”end” id=”end” type=”date” value=”@end.
ToShortDateString()” />
<input style=”background-colour: #afc1d9; border-radius: 8px; cursor: pointer;”
type=”submit” value=”submit” />
</form>

The date range will show the current date if the data set is empty, and the first and last date in the data set if there are records. There is minimal formatting on the submit button. Next, we are ready for the code that creates the grid:

@grid.GetHtml(mode: WebGridPagerModes.All, tableStyle: “tranlist”,
headerStyle: “headerstyle”, firstText: “First”, lastText: “Last”,
columns: grid.Columns( grid.Column(“TranDate”, header: “Trans Date”, format:
@<text>@item.TranDate.ToShortDateString()</text>),
grid.Column(“Description”, header: “Transaction Description”, style:
“bigcolumn”), grid.Column(“Units”, header: “Units”, style: “smallcolumn”),
grid.Column(“UnitPrice”, header: “Unit Price”, format: @<text>@item.UnitPrice.
ToString(“$0.00”)</text>, style: “medcolumn”),
grid.Column(“Total”, canSort: false, header: “Total Price”, format: @<text>@
{double q = (item.Units * item.UnitPrice);} @q.ToString(“$0.00”)</text>, style:
“medcolumn”),
grid.Column(“TransactionID”, header: “Action”, style: “linkcolumn”, canSort:
false,
format: @<text> @Html.ActionLink(“Edit”, “Edit”, new { id = item.TransactionID })
| @Html.ActionLink(“Delete”, “Delete”, new { id = item.TransactionID })</text>)))

The unformatted WebGrid again, but this time with values for the Total column being calculated in the controller

Creating a custom paging footer

The preceding code will give you the view with normal paging in the footer. Next we’ll customise the paging footer, putting the paging in the last column and the total record count in the second, by editing the HTML produced by the WebGrid helper. If you take this view in the browser and hit View Source, you will see that the paging is inside the tags <tfoot><tr><td>. We can pass the table from the WebGrid helper to a string and use the C# Replace method to edit the footer:

.ToString().Replace(“<tfoot><tr><td”,”<tfoot><tr class=’footstuff’><td></td><td>
Total Record Count ” + grid.TotalRowCount + “</td><td></td><td></td>
<td><td><td”)

This applies the footstuff class to the footer, creates both an empty column and one with the text we wanted to add, then puts in three more blank columns, and ends with the final <td partial tag that will be followed by the paging information. The next problem you have is that if you just return the string it will show as the markup text and won’t be shown as HTML. We fix this by wrapping all of this code in @MvcHtmlString.Create(…code goes here…). This takes the string you are returning and displays it as HTML. If you used grid.Rows.Count, it would show how many rows are on that particular page. You could use all of this data to show something like Records X to Y of XX. Right after the code that sets up the grid, you would write:

@{ int firstRecord = (grid.PageIndex * grid.RowsPerPage) + 1;
  int lastRecord = (grid.PageIndex * grid.RowsPerPage) + grid.Rows.Count();
}

This creates two page variables that hold values for the first and last records shown on the current page. The PageIndex property is a zero-based index of the current page, so you don’t need to subtract one before you multiply by the RowsPerPage to get the last record on the previous page. Then you add one to get the first record and add the number of rows on the current page to get the last record on the page. In the footer, you would use the following code in place of the code where the current code for Total Record Count is:

<td>Records ” + firstRecord + ” to ” + lastRecord + ” of ” + grid.TotalRowCount + “</td>

If you wanted the text for the record count to be in a different colour, you could apply a different class or even just use a style tag like the line below.

<td style=’colour: black;’>Records ” …</td>

Our finished formatted table, showing the custom formatting in the footer. This is used for paging, and to display the calculated values for the Records count
Via: http://www.creativebloq.com/web-design/create-custom-tables-webgrid-9134626

 

Advertisements

Create your own WordPress toolkit

Matt Cohen and Scott Basgaard of WooThemes show how to create a WordPress plug-in to enhance your custom WordPress projects, using best practices in plug-in development

Download the support files for this WordPress tutorial.

Since its inception back in 2003, WordPress has evolved from a blogging platform into a fully-fledged content management system. This process of evolution has spawned a new industry within the WordPress ecosystem, offering paid-for WordPress themes, plug-ins and other services.

Read the rest of this entry

Photoshop for web design 20 tips

For many web designers, Photoshop still plays an integral part in the website creation process. Whether you’re mocking up your entire site, or just designing individual site elements, here are some Photoshop web design tips that may prove useful for your next project…

01. Use grid systems

Grid systems for Photoshop
There are a number of tools to help you use grids in Photoshop

Grid systems can save a lot of headaches in web design. Try using free resources like Cameron McEfee’s GuideGuide Photoshop extension and the Grid System Generator to make custom grids easy and accurate.

Read the rest of this entry

Create a JavaScript bar chart with D3

Scott Murray, author of Interactive Data Visualization for the Web, demonstrates how to visualise data using the browser-based tool D3.js.

D3 (Data-Driven Documents), also known as D3.js, is a powerful tool for creating data visualisation within the browser. It’s a JavaScript library that leverages web standards that you already know to create future-proofed interactive visualisations that don’t rely on browser plug-ins. Start by downloading the code and opening up 00_page_template.html in a current browser. (You may need to view pages served through a web server, for example http://localhost/.)

Selection and creation

The page template provides only a reference to D3. Notice that the ‘body’ of the page is empty.

Open up the JavaScript console, and type in your first line:

d3.select(“body”)

Everything in D3 begins with a selection. You select something first; then you can tell D3 what you want to do with it.

D3’s select() and selectAll() methods both use CSS selector syntax (just like jQuery), so you can quickly identify any DOM element or elements you like. select() selects only the first element found, while selectAll() returns all matching elements.

We’ve selected the body; now let’s add something to it:

d3.select(“body”).append(“p”)

append() creates a new element inside the end of whatever selection you give it. So here, we create a new p paragraph at the end of the body.

Let’s throw some text into that paragraph:

d3.select(“body”).append(“p”).text(“Hello, world!”)

Now you should see “Hello, world!” rendered in the browser.

Well, hello!

All your data are belong to arrays

Switch to 01_data.html for a refresher on storing data in JavaScript. The simplest storage is one value in a single variable:

var value = 5;

Arrays can store multiple values. In JavaScript, arrays are defined with hard brackets:

var arrayOfValues = [ 5, 6, 7, 8, 10, 12, 22 ];

D3 is supremely flexible about data — as long as it’s in an array. Within an array, mix and match as you please. Instead of single values (as above), you could use objects.

Objects store arbitrary key/value pairs, and are defined with curly brackets. Here’s an array of objects:

var arrayOfObjects = [
{ plant: “fern”, color: “green”, number: 23 },
{ plant: “rose”, color: “pink”, number: 7 },
{ plant: “dandelion”, color: “white”, number: 185 }
];

Binding data to elements

I’ll use a straightforward array as our data set:

var dataset = [90, 45, 29, 88, 72, 63, 51, 35, 26, 20];

And I’ll set up some variables for our chart’s dimensions:

var width = 500;
var height = 200;
var barHeight = 20;

This doesn’t look like much yet, but as you can see, we’ve created one rectangle for each value in the data set — 10 in all

The Scalable Vector Graphics image format is amazing because its code is markup, just like HTML.

This simple SVG image contains a square and a circle.

<svg width=”100″ height=”100″>
<rect x=”0″ y=”0″ width=”50″ height=”50″></rect>
<circle cx=”50″ cy=”50″ r=”25″></circle>
</svg>

Styling SVG

Because SVG markup is HTML-compatible, all SVG elements will exist in the DOM.

As a result, they can be styled with CSS and manipulated dynamically with JavaScript.

I dare you to try that with JPGs!

Before we can draw anything, we have to create the SVG element inside which all the visual elements will reside:

var svg = d3.select(“body”).append(“svg”)
.attr(“width”, width)
.attr(“height”, height);

This selects the body and appends a new svg element. Then we use D3’s attr() method to set width and height attributes.

The selection of the new SVG element is passed back into a new variable called svg.

Storing selections this way allows us to reference elements later without having to re-select them.

Finally, brace yourself for D3’s most mind-bending pattern:

svg.selectAll(“rect”)
.data(dataset)
.enter().append(“rect”)
.attr(“x”, 0)
.attr(“y”, 0)
.attr(“width”, width)
.attr(“height”, barHeight);

Ack, what is this? First, within the SVG element, we select all the rect elements. Of course, there are none yet, but we’re about to create them!

Next, we call data(), which binds our data set to the selection. This is the fundamental process of D3: driving documents with data by linking one data value to one element.

For multiple values, we need multiple elements — say, one circle for each number. In this case, since there are more data values than matching DOM elements, data() not only binds the data, but creates an enter selection which represents all the incoming elements that do not yet exist.

Positioning

We use enter() to access the enter selection. Finally, append() fills each empty element with a new rect: these are the elements to which the data values are linked. Finally, several attr() statements set the properties of each new rect.

Open up 02_binding_data.html and inspect the DOM. We see there are 10 rectangles, but they’re all positioned on top of each other.

Here we’ve succeeded in creating a working horizontal bar chart, with 10 bars generated from 10 different data values

This is happening because we set the same x, y, width, and height values for each rect.

To prove that the data is now bound to elements, type d3.selectAll(“rect”) into the console. You’ll see an array of 10 SVG rect elements. Expand each one, and you’ll find a __data__ property, in which lives a data value!

The elements’ values are 90, 45, 29, and so on, just as specified in our original dataset array.

Setting attributes

Let’s rewrite the last four lines of the code above as:

.attr(“x”, 0)
.attr(“y”, function(d, i) {
return i * barHeight;
})
.attr(“width”, function(d) {
return d;
})
.attr(“height”, barHeight – 1);

All bars will be aligned along the left edge, so we can keep x at zero. But the y values must be spaced out to prevent overlap. To calculate dynamic values, we can specify an anonymous function instead of a static value.

Parameters Notice this function takes d and i as parameters, into which D3 will pass the current datum (the current value in the array) and its index position (0, 1, 2…). Although we don’t reference d yet, we must include it as a parameter so i is given the right value.

To get to grips with D3, check out Scott Murray’s forthcoming book Interactive Data Visualization for the Web, published by O’Reilly

Within this function, i * barHeight is calculated and returned as the y value, thereby pushing each successive rect further down the image.

For the width, we take d, the raw data value. And for height, we don’t need a function to calculate a dynamic value, since all bars will be the same height (barHeight – 1).

Now check out 03_setting_attributes.html!

Each bar gets a unique vertical position and a width that corresponds to the original array’s data value: a true visualisation!

Scaling data to pixels

This looks better, but the bars are too short. Our SVG is 500 pixels wide, yet the bars cover only a quarter of that.

Say hello to D3’s scales. Scales are customisable functions that map values from an input domain to an output range. We’ll use a scale to map values from the data’s domain (0 to 90) to pixel values (0 to 500).

To define our first scale:

var xScale = d3.scale.linear()
.domain([0, d3.max(dataset)])
.range([0, width]);

domain() takes an array with two values. The first value is the low end of the domain, while the second is the high values. d3.max() is a quick way to get the largest value from an array (90, in this case).

range() also takes as an array of two values, one low and one high. For us, these are pixel units, so we set them to zero and width.

One last thing: when setting each bar’s width, now we need to wrap d in our new scale function:

.attr(“width”, function(d) {
return xScale(d);
})

Brilliant! The data values have been mapped to visual pixel values, and therefore our bars now automatically scale to fit the image width.

In the screengrab above, the horizontal bars have been scaled to fit the width of the image

One step further

Taking this idea one step further, we can use an ordinal scale for the vertical axis.

This keeps our bars’ spacing and height flexible, so they can scale should our data set change in the future. Ordinal scales expect categories, not linear quantitative values, as input.

In this case, the ‘categories’ will be simply the position of each value in the data set: 0, 1, 2, and so on.

var yScale = d3.scale.ordinal()
.domain(d3.range(dataset.length))
.rangeRoundBands([0, height], 0.05);

d3.range() is a handy sequential integer generator, so the input domain here is set to [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], since dataset.length is 10.

rangeRoundBands() sets a banded output range that lines up nicely with pixel values — just what we need to space out the bars evenly, between 0 and height. The 0.05 tells D3 to add 5% for padding between bands.

D3 can handle more than bar charts, including zoomable geographic data, sortable tables and other interactive elements, like this map

Later, when setting the bars’ y and height values, instead of calculating those values from barHeight, we now reference our new ordinal scale:

.attr(“y”, function(d, i) {
return yScale(i);
})

.attr(“height”, yScale.rangeBand());

To specify basic interactions, bind the event listeners to elements using on():

.on(“click”, function() {
//Do something when this element is clicked
})

on() takes two arguments: first, the name of the DOM event that should trigger the function. This can be any standard JavaScript event. Let’s use mouseover and mouseout to highlight each bar on mouse hover:

.on(“mouseover”, function() {
d3.select(this).classed(“highlight”, true);
})
.on(“mouseout”, function() {
d3.select(this).classed(“highlight”, false);
});

Bar chart with mouse hover interaction. On mouseover, rects are assigned the ‘highlight’ class. On mouseout, the class is removed

Within each anonymous function, this represents “the current element,” so we can select it with d3.select(this). classed() adds or removes a class from any element. If true, the class will be added. If false, it is removed. Finally, we need a CSS style to recolour the bars when the highlight class is applied:

rect.highlight {
fill: purple;
}

(A colour change on hover like this could be achieved with CSS alone, but event listeners are needed for more complex interactions, like transitions.) Open up 05_interactivity.html: you’ve made a simple interactive bar chart!

Words: Scott Murray

Interactive Data Visualization for the Web: An Introduction to Designing with D3 by Scott Murray is available to buy from O’Reilly.

This article originally appeared in .net magazine issue 237. Thanks to Mike Bostock for his peer review of this tutorial

Liked this? Read these!

http://www.creativebloq.com/javascript/create-javascript-bar-chart-d3-9134563

4 ways to create CSS that’s modular and scalable

Several methods have emerged to help designers write scalable and modular HTML and CSS. Freelance web designer Steven Bradley presents an overview of four.

Modular and scalable CSS

Modular code is reusable code. It can be combined in a variety of ways, making it flexible and scalable, allowing you to iterate code blocks independently and leading to better performance and more maintainable sites.

Read the rest of this entry

Build a custom HTML5 video player

Media players that are built in to browsers vary in design. Ian Devlin explains how to use HTML5’s media API to build a custom player with a UI that stays consistent no matter what browser you use.

  • Knowledge needed: Intermediate HTML, intermediate JavaScript, intermediate CSS
  • Requires: Text editor, HTML5-enabled browser
  • Project time: 2-3 hours

Download the source files for this HTML5 tutorial

It’s common knowledge that with HTML5 websites you can play audio and video files directly in the browser without the need for third-party plug-ins, via the <audio> and <video> elements. But since the specification doesn’t define how the controls for audio and video files should look, each browser vendor has designed its own interface for its player, which of course provides a different user experience for each browser.

Read the rest of this entry

Adobe Creative Cloud: everything you need to know

2013 has been a big year for Adobe. Rather than jumping from CS6 to CS7, the design software giant instead released new ‘CC’ versions of Photoshop, Illustrator, Dreamweaver, After Effects, InDesign, and more, exclusively through its Creative Cloud subscription service. All new features and products will be released this way from now on – so unless you want to be stuck on CS6 forever, you need to sign up.

Are you going to subscribe? There’s a lot to take in before you make the decision, so here we’ve collected our articles about the Creative Cloud together in one handy post to help you out. See below to discover where you can find the exact details you’re looking for…

Read the rest of this entry

Build a basic responsive site with CSS

Responsive design is much misunderstood. Jason Michael lays to rest some myths, and then walks us through building a simple responsive website

 

Everyone’s talking about responsive web design. But does everyone understand what it’s for? I’m not sure. Many web designers and developers seem to me to have misunderstood the problem it’s trying to solve.

Put simply, it’s not about making sites for mobile devices, it’s about adapting layouts to viewport sizes.

In this tutorial I’ll look at the principles behind responsive web design in detail, so we’re sure to understand the concepts correctly. Once we’ve got that out of the way, I’ll walk you through building a website that scales perfectly on both large and small screens.

Responsive web design has mainly become a hot topic because more and more people are using mobile devices such as iPhones, iPads, and BlackBerrys to access the internet.
Read the rest of this entry

How to design great web forms

Need to make a web form? Unsure where to start? Jessica Enders has a recipe for forms that’ll work for you – and the people filling them in

This article first appeared in issue 240 of .net magazine – the world’s best-selling magazine for web designers and developers.

When it comes to forms, the temptation is to dive straight into the details. Do we need to collect phone numbers or just email addresses? Should this button say ‘Submit’ or ‘Apply’? And so on. But as with any successful design or development project, the best place to start is establishing the overall framework.

As the author of the famous Seven Habits of Highly Effective People, Steven R Covey, said: “Begin with the end in mind.” For forms, it’s important to clearly define what the form must achieve. The ‘six Ws’ of journalism are useful:

  • What information do we need to collect?
  • Why is that information needed?
  • Who is going to use this information?
  • How will the information be used?
  • When do we need the information?
  • Where is the information going to live?

You’ll see that these questions don’t talk about forms at all – their focus is on information. The form is just a tool for gathering this information. Therefore, its design should be determined by the information need. Discussing the above questions with key stakeholders will help elicit constraints, which will also influence the design of the form. These constraints may be about any part of the process, from the development platform (for example, to ensure connectivity with legacy systems) through to the need to collect data in particular formats (to be consistent with relevant standards, for instance).

Read the rest of this entry

%d bloggers like this: