John Dyer

Technology and web development in curly bracket languages {Javascript, C#, ActionScript}

Simple Cross-Browser HTML5 video with a single H.264 file and fallback options

by John Dyer 6. June 2010 01:32

At first glance, the promise of HTML5 <video> seems awesome. Just a simple

<video src="myvideo.mp4" controls></video>

and you're done right? Not quite. In reality there are all kinds of browser inconsistence that make this impossible. Here's a run down of the problems:

1. Older browsers don't support <video>

Only the most recent versions of the big five (Firefox, Chrome, Safari, IE, Opera) support <video>, so you have to have a fallback solution of some kind if you want to use <video> and still support your audience.

2. Newer browsers don't support the same codecs

Sadly, different browsers support different codecs. H.264 works in Chrome, Safari, and IE9, while Firefox and Opera only support Ogg/Vorbis. All the major browser vendors have pledged support for Google's recently released WebM format, but this will take some time for the browers and encoding software to catch up.

3. Fallback HTML requires multiple video files

The most common solution offered is to use nested HTML to allow browsers that don't support <video> to fallback to flash. One of the best of these is called Video for Everybody and looks something like this:

<video>
   <source src="myfile.mp4">
   <source src="myfile.ogg">

   <object src="flashplayer.swf?file=myfile.mp4">
      <embed src="flashplayer.swf?file=myfile.mp4">
   </object>
</video>

This works in all browsers, but it has a major problem: You must have two video files. If you attempt to use only MP4, Firefox on Opera will fail. If you remove the <source src="myfile.ogg">, Firefox and Opera will not fallback to the Flash <object>. They will just display a big, blank, black box with an X. The same goes if you only use OGG on browsers that don't support OGG, or attempt to use WebM.

The HTML fallback mechanism only works if the browser doesn't understand the <video> tag. It doesn't work if it doesn't understand the <source> file. So if you want to only use one file, then you must use JavaScript.

A Simple JavaScript Solution

Since I don't want to maintain two versions of every video, I need a way to fallback to Flash for non-H.264 browsers. Here's my simple solution using jQuery.

<video id="my-video">
   <source src="myfile.mp4" type="video/mp4">
</video>

<script>
(function() {
  var video = document.createElement("video");
  if ( typeof(video.canPlayType) == 'undefined' || // detect browsers with no <video> support
       video.canPlayType('video/mp4') == '') { // detect the ability to play H.264/MP4

       var video = $('#my-video');
       var videoUrl = video.find('source').attr('src');
       var flashUrl = '/flash/myplayer.swf';

       // create flash        
       var flash = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ' +
				'	codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" ' +
				'	width="' + video.width() + '" height="' + video.height() + '" id="fallbackplayer">' +
				'		<param name="allowfullscreen" value="true" /> ' +
				'		<param name="movie" value="' + flashUrl + '?mediaUrl=' + videoUrl + '" /> ' +
				'		<embed id="dtsplayer" width="' + video.width() + '" height="' + video.height() + '" allowfullscreen="true" allowscriptaccess="always" ' +
				'			quality="high" name="fallbackplayer" ' +
' src="' + flashUrl + '?mediaUrl=' + videoUrl + '" ' + ' type="application/x-shockwave-flash" /> ' + '</object>'; // insert flash and remove video video.before(flash); video.detach(); } })(); </script>

The code is fairly simple. It just checks if the browser understands the <video> tag by checking for the "canPlayType" function, then it uses canPlayType to determine if the browser can play an H.264/MP4. If not, it inserts Flash as a fallback.

Please note: This is a simplified script for example purposes only. It needs flash version detection, and it should be turned into a jQuery extension, but it should still be a nice guide for 

Purple CMS - Now on Github

by John Dyer 7. May 2010 16:50

A few months ago, I put out a preview of a ASP.NET 4.0 CMS called "Purple" (named for the official color of Dallas Theological Seminary). 

I'm now pushing updates to Github, so if you're interested go grab a copy here

http://github.com/johndyer/purple

About Purple

Purple is a CMS that uses .NET's URL Routing to quickly create a website using normal .NET tools like Masterpages and ASCX controls. It has versioning controls for every page and allows you to edit in page rather than through a backend editing area and stores everything in either XML or SQL for rapid development.

<table> to JSON

by John Dyer 5. May 2010 16:19

I am updating a tool that allows users to customize a large data table to their needs. It's sort of like a progressive insurance for seminaries in that it helps students compare information on about 30 US seminaries so they can make an informed decision about where to go.

My initial approach when I built it 4-5 years ago was to embed JSON data in the HTML page and then use JavaScript to convert that JSON data into a table based on the user's choices.

But there are a few problems with this approach.

  1. The data is not accessible to screen readers.
  2. The data is not accessible to those without JavaScript
  3. Embedding a lot of JSON data in an HTML page isn't a very good idea. It should be a separate cached .js file, but I can't do that since the data often changes and it still wouldn't address #1 and #2

So I've decided in the new version to start with a large <table> and then turn that table into JSON data using the <thead> region as the JSON labels. Then I can take that data and customize it based on the user's choices. Interestingly the overall data size is a bit smaller since writing a <td> and </td> for each peice of information is actually smaller than writing the header name and quotes over and over.

Here's the simple table to JSON code. It assumes the first row is has header names and removes spaces and lower cases it.

function tableToJson(table) {
	var data = [];
	
	// first row needs to be headers
	var headers = [];
	for (var i=0; i<table.rows[0].cells.length; i++) {
		headers[i] = table.rows[0].cells[i].innerHTML.toLowerCase().replace(/ /gi,'');
	}
	
	// go through cells
	for (var i=1; i<table.rows.length; i++) {
		
		var tableRow = table.rows[i];
		var rowData = {};
		
		for (var j=0; j<tableRow.cells.length; j++) {
			
			rowData[ headers[j] ] = tableRow.cells[j].innerHTML;
		
		}
		
		data.push(rowData);
	}		
	
	return data;
}

 

 

Below are links to the two pages for comparison. Please note that the site where the "new" page is is still a work in progress and won't be launched for a month or two.

 


 

HTML5 Video Player with Slides and Transcript

by John Dyer 26. April 2010 16:34

A few weeks ago I created an HTML5 version of DTS's online video player application. A few years ago, when Flash 9 enabled H.264 playback, we switched all of our video from the FLV format to MP4s encoded with the H.264 codec so that our videos could work on as many places as possible, especially Apple's iPod and iPhone.

I didn't initially plan to work the the HTML5 <video> tag because of all the browser support and formatting issues, but with the advent of the iPad and IE9's support for H.264 it makes sense to start using it. I wish that Firefox would support H.264 as well or at least fall back helpfully, but until it does, we will only support Webkit and IE9.

The Player

The player begins in a landscape format with a small video frame and larger slides, but it can also switch to portrait mode and an alternate layout by clicking on the buttons in the lower right. On an iPad, it automatically sense the orientation and rotates accordingly.

Portrait Version

The Code

To code the player, I build a generic MediaPlayer JavaScript object which abstracts out several HTML5 JavaScript APi methods and events. Other than handling HTML5 Media Events, the main thing it does is store and fire Time Cue events much like Flash's MediaPlayer API (see addASCuePoint). This allows me to add events for syncing the transcript and slides and also handling the UI for controls. On top of the core MediaPlayer object, I built a DtsController which handles choosing a class and building the visual environment for slides and transcript. The timing code looks like this:

player.addCuePoint('event-title', 66); player.addEventListener('cuepoint', function (e) { console.log('fired', e.name, e.time); });

To keep it relatively lightweight, I didn't use a library like jQuery, but instead used HTML5's document.querySelector and some custom animation methods to achieve the scrolling and fading effects. I only wish it were as elegant as Thomas Fuch's emile library.

Try it Out

If you're interested in the player or the code head to (using a WebKit browser like Safari or Chrome)

http://my.dts.edu/player-html5

Hopefully, the next preview of IE9 will enable the HTML5 <video> tag and let me clean it up for the final version of IE9. Once that happens, we'll abandon the Flash version of the player and go completely HTML5.

Purple CMS - Super Early Alpha (0.1)

by John Dyer 3. March 2010 17:00

A few years ago, I built a CMS for Dallas Theological Seminary that has served us pretty well. It has some features we really wanted, but to get them I had to hack up the ASP.NET 2.0 page life cycle to get it to work. With ASP.NET 4.0, a lot of what I did is much easier and can be done "normally" instead of with things that felt like hacks. 

Project Requirements

Different projects require different kinds of CMS packages, but here were my requirements:

  • Extensionless URLs (no .aspx on the end of URLs) - this was harder in ASP.NET 2.0, but in ASP.NET 4.0 especially on IIS7 this is much easier.
  • Normal Masterpages - I don't want a special, proprietary template engine. I just want to use normal ASP.NET features so that people can work on the site without learning an new language and use Visual Studio if they want.
  • WebForms and *.ascx Controls - I love using MVC on certain projects, but for a site with lots of pages (DTS has around 1000 pages), I need to be able to use simple *.ascx controls. We have lots of pages with various repeaters and forms to fill out and using MVC controllers for each it too much to maintain. Personally I like <script runat="server"> rather than codebehind or codebeside so we can keep a site agile.
  • Not require <form runat="server"> - A lot of pages with plain HTML or just a <asp:repeater> don't need viewstate, so there is no need to have ASP.NET form on every page. The CMS is smart enough to wrap content in <form runat="server"> if needed, but not otherwise.
  • No takeover - The CMS can't take over the entire site and not allow other normal ASP.NET functionality like pages (*.aspx) and handlers (*.ashx).
  • In page editing - This isn't really a requirement, but I like being able to edit a page in place rather than have to go to a separate admin area. 


    Click "edit" and then you go to:


  • Page versioning - Of course we need to be able to rollback to a previous version. Nothing too complex, just a list of revisions with dates.
  • XML or SQL - A nice CMS shouldn't have to use SQL for a 10 pages site. For now, XML is the default.
  • Permissions - We don't need a complex workflow, but we need to be able to specify a role for super admin and a role for users who can be assigned edit access to special pages. It needs to work with ASP.NET Membership and Roles.
  • Redirects - A small feature, but we use a lot of vanity URLs in print advertisements that need to go somewhere else (www.dts.edu/thm -> www.dts.edu/admissions/degrees/thm)
  • Complex URL handling - I also want to be able to create a page that has wildcard handling for all sub pages. For example, I want a page that lists a faculty (www.dts.edu/about/faculty) but can also handle and sub pages and show an individual faculty member (www.dts.edu/about/faculty/dbock). This also allows things like blogs or forums if someone wanted to make those.

Download Purple CMS 0.1

I've put up a very rough demo you can try out. The permissions, redirects, and "complex URL handling" are not yet finished in this build, but the main ability to use masterpages, controls, and edit pages with HTML is in the demo. It looks just like the default ASP.NET site and allows you to login and edit pages.

To use it, you'll need Visual Studio .NET 2010 RC and .NET 4.0 RC. Just unzip the file, run the solution, and hit "Debug" or point your local IIS to the website folder and select "ASP.NET 4.0" it's Application Pool.

Let me know what you think.

Experimenting with Web SQL databases

by John Dyer 27. February 2010 17:05

&

What is Web SQL?

Web SQL (http://www.w3.org/TR/webdatabase/) is proposed technology that allows a small SQL database to reside inside a browser. Instead of making AJAX calls back and forth from server to client whenever any information is needed, the data is stored locally in the browser so it can be quickly queried and used. Web SQL is not technically part of HTML5, but it is part of a group of technology suggestions for the future of the web.

Currently, Web SQL is only implemented in WebKit based browsers (Safari, Chrome, iPhone) and beta versions of Opera. Google Gears also had a local database implementation, but Google Gears is being discontinued in favor of HTML5.

How Does Web SQL Work?

HTML5 Doctor has a great article on using Web SQL, so I'll only repeat a small code sample.

 

// create/open database
var db = openDatabase('mydb', '1.0', 'my first database', 2 * 1024 * 1024);

// start transaction, create table, insert data
db.transaction(function (tx) {
amp;nbsp; tx.executeSql('CREATE TABLE IF NOT EXISTS foo (id unique, text)');
  tx.executeSql('INSERT INTO foo (id, text) VALUES (1, "synergies")');
});

// query the data
db.transaction(function (tx) {
  tx.executeSql('SELECT * FROM foo', [], function (tx, results) {
    var len = results.rows.length, i;
    for (i = 0; i < len; i++) {
      alert(results.rows.item(i).text);
    }
  });
});

 

A Giant Web SQL example

Web SQL is great for small amounts of data. The Webkit team has a sample which creates and stores notes (http://webkit.org/demos/sticky-notes/index.html), while HTML5 doctor stores recent tweets (http://html5demos.com/database).

I wanted to load a lot more data to see what the performance would be, so I decided to load the entire Greek New Testament which is around 170,000 words along with its morphology information (part of speech, declension, etc.). It attempts to load entire books at a time and then allow you to pull up a chapter. You can also click on a word and see every time it is use in the Greek Bible. Once the database is loaded, you can come back to the site at any time and never have to reload the database. It will always be there in your browser. 

Try it out:

The Greek New Testament in Web SQL

Gotchas: The database is a little over 5MB which breaks the limit in Google Chrome. Safari will ask you if you want to increase the storage, but it will also stop the loading processing while it waits for the user to respond. If you use Safari, you can click the "Toggle DB Admin" then click "Delete all" and then "Load all" to clear out and then reload the entire database.

Optimizing CSS with Base64 Embedded Images (with Bonus Utility!)

by John Dyer 26. January 2010 18:42

 

As I design a new site (current site | early demo of new site), I am working through what combination of technologies (CDN, sprites, caching, gzipping, etc.) we want to use to optimize it. One tool I’m looking at is embedding images in CSS with base64 strings. Instead of the browser needing to make several calls, one for the CSS file and then one for each image, base64 embedding means that all of the images are embedded within the CSS file itself.

It’s great for small images or images that only show up on :hover or mouseover and you don't want there to be any delay in the image appearing. Here’s what it looks like:

Normal CSS

.myclass {
width: 45px;
background: transparent url(myimage.jpg) top left no-repeat;
}

CSS with Base64 Embedded Image

.myclass {
width: 45px;
background: transparent url(data:image/png;base64,LONG-STRING-OF-BASE64-TEXT) top left no-repeat;
}

Problems with Base64

  1. Works in all browsers except IE6 and IE7. Solution: use a conditional comments to give IE6/7 a stylesheet that still references the images.
  2. Base64 is bigger than real images: In my tests a base64 encoded string image is somewhere around 150% the size of a regular image. This means it’s unusable for large images.
  3. Hard to manage: If you change the image, you’ll need to reembed the base64 string. You also have to maitain a separate IE stylesheet.

How to manage it

To help figure out which images were worth embedded and help manage it, I developed a small utility that analyzes a CSS file and allows you to select which images you want to embed. You can also preselect them by adding a comment somewhere within your CSS declaration that says /*embed*/

What It Does

  • Finds all image URLs in your CSS file (note: no CSS3 multiples or borders)
  • Shows the size difference between the image and the base64 string
  • Shows the final size output size and the GZipped size for comparison to the original
  • Removes comments and whitespace if you want
  • Creates a new base64 stylesheet and a IE6/7 stylesheet with references to the original image

Download

Refactoring the JavaScript Color Picker - Step 1: Clean up the HTML and CSS

by John Dyer 19. November 2009 20:03

On of the most popular posts on this blog was a color picker (demo) I created about 4 years ago and then released 2 years ago. It was based on the Prototype library which at the time was the only major mega-JavaScript library. Since then, others have ported the color picker to jQuery, MooTools, YUI, and other libraries, and it's popularity can be seen by searching for "javascript color picker" on Google.

The Original Color Picker (mimics Photoshop)

Color Picker Example

Rebuilding Goals

If the original color picker was popular, it was because of it's functionality, not so much pretty code. So, I'd like to rebuild the color picker with a few goals in mind:

  1. Be library independent - I'll have to add a little bit of extra code for things like event management, but this will allow it to work for everyone.
  2. Small and fast - The original JavaScript isn't too slow, but the color picker uses lots of separate images (27!). Originally, I hid these inside a <div> so that the browser would keep them cached, but I'd like to combine them into a few sprites to speed up the load time.
  3. Clean up the HTML/CSS - The original has a lot of inline styles and unnecessary complexity, making it ugly and unwieldy.
  4. Clean up the JavaScript - The original code separated out some functionality which makes it harder to figure out what's going on. I plan bring these together, so that I have one class for color conversion, one class for slider functionality, and one class for the color picker. The new code will also include code to function as a plugin to the major existing libraries (jQuery, Prototype, Mootools, YUI, etc.).

The first big step is to clean up the HTML and CSS. To get a feel for the old HTML/CSS, check out the version 1 example page. Here's what I've come up with so far:

Color Picker CSS

.color-picker
    { border: 0; padding: 0; margin: 0; font-family: Tahoma; font-size: 12px;}
.color-picker table, .color-picker td
    { border: 0; margin: 0; padding: 0; vertical-align: top;}   
.color-picker label
    { margin: 4px 0; display: block;}
.cp-container
    { position: relative; float: left; border: solid 1px #000; padding: 0px; }
.cp-layer1, .cp-layer2, .cp-layer3, .cp-layer4
    { display: block; position: absolute; top: 0px; left: 0px; }   
.cp-map
    { width: 256px; height: 256px; margin: 0px; }
.cp-map div
    { width: 256px; height: 256px; position: absolute; top: 0; left: 0; background: transparent url(maps.png) 0px 0px no-repeat;}
.cp-bar
    { width: 20px; height: 256px; margin: 0px 9px;}
.cp-bar div
    { width: 20px; height: 256px; position: absolute; top: 0; left: 0; background: transparent url(bars.png) 0px 0px no-repeat;}
.cp-preview
    { width: 60px; height: 60px; padding: 0px; margin: 0px; border: solid 1px #000; }
.cp-hsv, .cp-rgb
    { width: 40px; }
.cp-hex
    { width: 55px; }
.cp-map-arrow
    { background: transparent url(map-arrow.gif) 0px 0px no-repeat; width: 40px; height: 9px; position: absolute;}
.cp-bar-arrow
    { background: transparent url(bar-arrow.gif) 0px 0px no-repeat; width: 15px; height: 15px; position: absolute;}

Color Picker HTML

<div id="cp1" class="color-picker">
    <table cellpadding="0">
    <tbody><tr>
        <td>
            <div class="cp-container cp-map">
                <div class="cp-layer1"></div>
                <div class="cp-layer2"></div>       
            </div>
        </td>
        <td>
            <div class="cp-container cp-bar">
                <div class="cp-layer1"></div>
                <div class="cp-layer2"></div>
                <div class="cp-layer3"></div>
                <div class="cp-layer4"></div>                   
            </div>
        </td>
        <td valign="top">
            <table><tbody>
            <tr>
                <td colspan="3">
                    <div class="cp-preview"></div>
                </td>
            </tr>
            <tr>
                <td><input type="radio" /></td>
                <td><label>H:</label></td>
                <td><input class="cp-hsv" type="text" /> &#176;</td>
            </tr>
            <tr>
                <td><input type="radio" /></td>
                <td><label>S:</label></td>
                <td><input class="cp-hsv" type="text" /> %</td>
            </tr>
            <tr>
                <td><input type="radio" /></td>
                <td><label>B:</label></td>
                <td><input class="cp-hsv" type="text" /> %</td>
            </tr>
            <tr>
                <td><input type="radio" /></td>
                <td><label>R:</label></td>
                <td><input class="cp-rgb" type="text" /></td>
            </tr>
            <tr>
                <td><input type="radio" /></td>
                <td><label>G:</label></td>
                <td><input class="cp-rgb" type="text" /></td>
            </tr>
            <tr>
                <td><input type="radio" /></td>
                <td><label>B:</label></td>
                <td><input class="cp-rgb" type="text" /></td>
            </tr>
            <tr>
                <td>#</td>
                <td colspan="2">
                    <input class="cp-hex" type="text" />
                </td>
            </tr>
        </tbody></table>
        </td>
    </tr></tbody>
    <div class="cp-map-arrow"></div>
    <div class="cp-slider-arrow"></div>
</div>

Cleanup Comments

To make it more readable, I've removed all the id attributes except for the single id on the containing div, taken out all inline styles, and moved the CSS to a separate file. I also changed the layers to <div> tags with background images instead of <img> tags. This may present some problems with IE6 opacity down the road, so I might need to change it back. I've also removed z-index values from the CSS to prevent problems with other JavaScript controls on the page. I was not careful with DOCTYPE in the past, but the new HTML and CSS should work in any DOCTYPE (I'll be using the HTML5 DOCTYPE in all the examples). Finally, the arrows are created using <div> that are inside the main block, which will make it easer to show and hide the entire color picker.

Bar Sprite

As a preview, I'm including the sprite for the value bar of the color picker. This combines 14 different bars into one 1.77KB file. Next time, we'll talk about memory consumption and sprites and see if the sprite usage is actually helpful.

new color bars sprite

HTML5 (XHTML5) Validation Schema and Intellisense for Visual Studio 2008

by John Dyer 21. July 2009 20:46

I've been playing around with HTML5 (nice intro at Smashing Magazine) for a side project, and I wanted Visual Studio 2008 to stop telling me the new elements were not valid. So I created a new Validation Schema for Visual Studio 2008 that implements much of the HTML5 spec. I found some hints on how to do this in Visual Studio 2005 and went from there. Here's a pic of it in action giving you the attributes of of the new <source> tag under a new <video> tag:

Readme.txt

  • There is a lot of confusion about HTML, XHTML, and mime-types. I've chose to go with a stricter XML-like syntax of closed tags and quoted attributes, rather than the looser HTML, so I called it "XHTML 5" although that doesn't really make it offically XHTML 5 until you do the rest of the research, work, and fun.
  • This is not a 100% perfect implementation. There are bound to be different interpretations of what's "correct" HTML5 and you have until 2022 to get it right, so please don't worry about it too much.

What's Finished

  • All the new elements in HTML5 have been added in the follow groupings
    • structure: article, aside, footer, header, nav, section
    • media: audio, video, source
    • other: bb, canvas, command, datagrid, datalist, details, dialog, eventsource, figure, hgroup, keygen, mark, menu, meter, output, progress, time
  • When new elements have custom attributes (such as height and width for video, I've tried to add those)
  • I've also changed a few things like not requiring the type attribute on script blocks and allowing meta tags to have a charset attribute
  • I've begun adding HTML5 events (ondrag, onplay, etc.) but have not completed all of them
  • I am not sure how to add HTML5 style data- attributes, so those won't validate yet.

How to Use it

  1. Download XHTML Validation Schema for Visual Studio 2008
  2. Save it to C:\Program Files\Microsoft Visual Studio 9.0\Common7\Packages\schemas\html\
  3. Add the following to the Registry:
    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Packages\{1B437D20-F8FE-11D2-A6AE-00104BCC7269}\Schemas\Schema 23]
    "Friendly Name"="XHTML 5"
    "URI"="http://schemas.microsoft.com/intellisense/xhtml5"
    "File"="html\\xhtml5.xsd"

    Note that you might need to change "Schema 23" to something else if you already have other non-default schemas installed. You just need to use the next available number in the list.

I hope you find it helpful. Please let me know if you end up using it and feel free to suggest updates or corrections.

MVC Edit View Template Upgrades

by John Dyer 11. March 2009 22:11

I’m building a new LMS using ASP.NET MVC and I am making heavy use of the View templates added in RC1. (see: T4 Templates: A Quick-Start Guide for ASP.NET MVC Developers)

I made a few changes to the default template to allow (1) table rows and cells instead of <p> tags, (2)add spaced to “ProperyName” so it looks like “Property Name”, and (3) use reflection to determine the <input> type generated by the Html helper. For all string Properties, a normal <input type=”text” /> is still generated, but for Int32, I am generating a <select> and for Booleans, a <input type=”checkbox” /> since these are the normal fields I use for forms.

For an object that looks like this

public class Person {
public string FullName { get; set; }
public bool IsActive { get; set; }
}

The default Edit View looks like this:

<p>
<label for="FullName">FullName:</label>
<%= Html.TextBox("FullName") %>
<%= Html.ValidationMessage("FullName", "*") %>
</p>
<p>
<label for="CampusID">IsActive:</label>
<%= Html.TextBox("IsActive") %>
<%= Html.ValidationMessage("IsActive", "*") %>
</p>

Here's what I wanted the Edit View to look like:

<tr>
<td class="form-title"><label for="FullName">Full Name</label></td>
<td class="form-input"><%= Html.TextBox("FullName") %></td>
<td class="form-val"><%= Html.ValidationMessage("FullName", "*") %></td>
</tr>
<tr>
<td class="form-title"><label for="Password">Is Active</label></td>
<td class="form-input"><%= Html.CheckBox("IsActive") %></td>
<td class="form-val"><%= Html.ValidationMessage("IsActive", "*") %></td>
</tr>

Here’s how I handled the different property types

Property Type Html Helper Output
String (and others) Html.TextBox <input type="text" />
Boolean Html.CheckBox <input type="checkbox" />
Int32 Html.DropDownList <select>

You can modify this easily in the code below to put whatever controls you want for each property type. To use the template, just create a folder in your project called CodeTemplates\AddView:

image

Here is my are the parts of Edit.tt file that I updated:

<#
    
if(!String.IsNullOrEmpty(mvcHost.ViewDataTypeGenericString)) {
List<PropertyInfo> properties = new List<PropertyInfo>();
FilterProperties(mvcHost.ViewDataType, properties);
#>
<%= Html.ValidationSummary() %> <% using (Html.BeginForm()) {%>


<table class="form-admin">
<#
foreach(PropertyInfo pi in properties) {
#>
<tr>
<td class="form-title"><label for="<#= pi.Name #>"><#= FormatLabel(pi.Name) #></label></td>
<td class="form-input"><%= Html.<#= GetInputType(pi) #>("<#= pi.Name #>") %></td>
<td class="form-val"><%= Html.ValidationMessage("<#= pi.Name #>", "*") %></td>
</tr>
<#
}
#>
</table>
<input type="submit" value="Save" />
<% } %>


<div>
<%=Html.ActionLink("Back to List", "Index") %>
</div>
<#+
public string FormatLabel(string label) {
return System.Text.RegularExpressions.Regex.Replace(label, "([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))", "$1 ");
}


public string GetInputType(PropertyInfo pi) {
switch (pi.PropertyType.ToString()) {
case "System.Int32":
case "System.Int64":
return "DropDownList";
case "System.Boolean":
return "CheckBox";
case "System.String":
default:
return "TextBox";
}
}



public void FilterProperties(Type type, List<PropertyInfo> properties) { if(type != null) {
PropertyInfo[] publicProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);


foreach (PropertyInfo pi in publicProperties)
{
if (IsBindableType(pi.PropertyType) && pi.CanRead && pi.CanWrite)
{
properties.Add(pi);
}
}
}
}
#>

Hope this is helpful to you!

Web Statistics