One of the new global attributes in HTML5 is the hidden attribute. It is not the most advanced or revolutionary attribute in HTML5, since all it does is actually to hide the content of the element.

To use it, all you have to do is to add it to an element, and you can see that the content is gone.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Hidden attribute</title>
</head>
<body>
    <h1>Hidden attribute</h1>
    <div>I´m visible!</div>
    <div hidden>I´m invisible!</div>
</body>
</html>

Result:

screen

The purpose of this attribute is to tell the browser that its content is irrelevant as it is, but could be used to store elements or information that you might need to use with JavaScript for example.

Since it is not available in IE 10 and earlier (introduced in IE 11), the attribute will be ignored. To hide it in older browsers, all you have to do is to add some CSS:

<style>
    [hidden] {
        display: none;
    }
</style>

This is only going to hide the content as long as CSS is activated and parsed, while browsers with support for the attribute will hide the content whether or not CSS is activated.

Last time I wrote about how to use Polymer to create custom elements. This time we will create two custom elements, where one of them is going to use the other to add additional functionality. We will also use CSS Filters and properties unique to this element.

If you don´t know what Polymer is and how to get it, please read my last post about it.

As I demonstrated in the last post, it´s really easy to create a new custom element and use it on your page. An element is not always a simple control though, but can be a collection of different controls. We could add all these controls into one huge element, or we could create smaller components which we will use together in a new element.

In this post I will create a new element (x-filter) which uses CSS Filters, and that element will be used in another element (x-choosefilter) which will have a dropdown list where we can choose which filter we want to use. The x-filter element will be able to set the filter on any element we want, so we will need to make it possible to add additional elements inside of it.

This is how we will use the elements on the page with x-choosefilter:

1 - Diagram

Since the x-filter element is just an ordinary element, we will also be able to use that directly on the page.

The first thing we will have to do here is to create the x-filter element.

<element name="x-filter" attributes="filter">
    <template>
        <style>
            .grayscale {
                -webkit-filter: grayscale(100%);
                -moz-filter: grayscale(100%);
                -ms-filter: grayscale(100%);
                -o-filter: grayscale(100%);
                filter: grayscale(100%);
            }
 
            .blur {
                -webkit-filter: blur(3px);
                -moz-filter: blur(3px);
                -ms-filter: blur(3px);
                -o-filter: blur(3px);
                filter: blur(3px);
            }
 
            .brightness {
                -webkit-filter: brightness(25%);
                -moz-filter: brightness(25%);
                -ms-filter: brightness(25%);
                -o-filter: brightness(25%);
                filter: brightness(25%);
            }
 
            .contrast {
                -webkit-filter: contrast(50%);
                -moz-filter: contrast(50%);
                -ms-filter: contrast(50%);
                -o-filter: contrast(50%);
                filter: contrast(50%);
            }
 
            .dropshadow {
                -webkit-filter: drop-shadow(5px 5px 5px rgba(0, 0, 0, 0.5));
                -moz-filter: drop-shadow(5px 5px 5px rgba(0, 0, 0, 0.5));
                -ms-filter: drop-shadow(5px 5px 5px rgba(0, 0, 0, 0.5));
                -o-filter: drop-shadow(5px 5px 5px rgba(0, 0, 0, 0.5));
                filter: drop-shadow(5px 5px 5px rgba(0, 0, 0, 0.5));
            }
 
            .huerotate {
                -webkit-filter: hue-rotate(180deg);
                -moz-filter: hue-rotate(180deg);
                -ms-filter: hue-rotate(180deg);
                -o-filter: hue-rotate(180deg);
                filter: hue-rotate(180deg);
            }
 
            .invert {
                -webkit-filter: invert(100%);
                -moz-filter: invert(100%);
                -ms-filter: invert(100%);
                -o-filter: invert(100%);
                filter: invert(100%);
            }
 
            .opacity {
                -webkit-filter: opacity(50%);
                -moz-filter: opacity(50%);
                -ms-filter: opacity(50%);
                -o-filter: opacity(50%);
                filter: opacity(50%);
            }
 
            .saturate {
                -webkit-filter: saturate(1000%);
                -moz-filter: saturate(1000%);
                -ms-filter: saturate(1000%);
                -o-filter: saturate(1000%);
                filter: saturate(1000%);
            }
 
            .sepia {
                -webkit-filter: sepia(100%);
                -moz-filter: sepia(100%);
                -ms-filter: sepia(100%);
                -o-filter: sepia(100%);
                filter: sepia(100%);
            }
        </style>
        <div id="filter" class="{{ filter }}">
            <content></content>
        </div>
    </template>
    <script>
        'use strict';
 
        Polymer.register(this, {
            filter: '',
            setFilter: function (test) {
                this.$.filter.className = test;
            }
        });
    </script>
</element>

As you can see, we have a couple of CSS classes which uses one filter each. We are not going to implement support for different values for each class in this element, but that is something you could add if you want to. You will just have to change the JavaScript to take care of the value as well. We could also make it possible to sett the filter more dynamically instead of having one class for each, but for this demo I don´t feel that it´s necessary.

Since we use content element inside of <div id=”filter” …></div>, everything we send to the x-filter element will be styled with the filter we have chosed.

To test this, we will add a new HTML page (index.html):

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>CSS Filters</title>
    <link rel="import" href="x-filter.html">
    <script src="polymer.min.js"></script>
</head>
<body>
    <h1>CSS Filters</h1>
    <x-filter filter="sepia">
        <img src="image.jpg" />     
    </x-filter>
</body>
</html>

We have added an import link in head, and havet hen added the x-filter element with the filter set to ”sepia” and the content to an image we have. If we open the page now, we will se this:

2 - Sepia demo

The image which is just a normal photo, have instead got a sepia filter. At the moment, this demo only works in Chrome (I am using Chrome Canary 29) since CSS Filters isn´t fully implemented in other browsers.

The next step is to add a dropdownlist where we can use different filters and switch easily. To do this we will create a new HTML page for the new x-choosefilter element.

<element name="x-choosefilter">
    <template>
        <select id="selectedfilter" on-change="setfilter">
            <option value="">None</option>
            <option value="grayscale">Grayscale</option>
            <option value="blur">Blur</option>
            <option value="brightness">Brightness</option>
            <option value="contrast">Contrast</option>
            <option value="dropshadow">Drop shadow</option>
            <option value="huerotate">Hue rotate</option>
            <option value="invert">Invert</option>
            <option value="opacity">Opacity</option>
            <option value="saturate">Saturate</option>
            <option value="sepia">Sepia</option>
        </select>
 
        <x-filter id="xfilter">
            <content></content>
        </x-filter>
    </template>
    <script>
        'use strict';
 
        Polymer.register(this, {
            filter: 'opacity',
            setfilter: function () {
                this.$.xfilter.setFilter(this.$.selectedfilter.value);
            }
        });
    </script>
</element>

We create this element the same way as before, but we will send the content into the x-filter element from this one. When we change the value for the dropdown list, we call the setFilter(…) method which we created in the x-filter element.

If we want to use this element, we will have to add an link to index.html, and then add the element. We will still need to have the link to x-filter in index.html.

The new and improved index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>CSS Filters</title>
    <link rel="import" href="x-filter.html">
    <link rel="import" href="x-choosefilter.html">
    <script src="polymer.min.js"></script>
</head>
<body>
    <h1>CSS Filters</h1>
 
    <x-choosefilter>
        <img src="image.jpg" />
    </x-choosefilter>
</body>
</html>

If we open the page now, we will have the dropdown list where we can change filter.

3 - Dropdown

We are now able to choose between the different CSS Filters we provide, by simply adding the x-choosefilter element. We can still use x-filter though, and if we add it on the same page after the x-choosefilter element we will see this:

4 - Both elements

Since the elements have their own scopes with their own Shadow DOM they don´t affect each other. It means that we can add both this elements to existing web sites without breaking anything.

Thanks to a new specification from W3C called ”Custom Elements” we will be able to create our own elements such as <x-stock symbol=”MSFT” /> and use that element as any other element in our browsers, which includes custom styling, custom events, custom APIs etc.

I previously blogged about Shadow DOM where I demonstrated how to use the Developer tools in Google Chrome to get the underlying DOM that is not visible to the user, in this case the video element. This is a great tool to get more understanding about how the element is actually built, and the API makes it possible to create our own Shadow DOM with ”hidden” elements.

This time we will not inspect the current video element, but instead we will create a new element that is using the video element underneath, while providing separate APIs and menu controls. Since the browser support is very limited so far, I am going to use Polymer, which allows us to use HTML Imports, Custom Elements and Shadow DOM in all major browsers. The library is still in pre-alpha mode and is not stable enough for production environments, so you should only use this for experimenting for the moment.

Get the latest Polymer

Polymer is hosted on Github, and if you like me, are using Visual Studio 2012 for web development, you should download Update 2and the Git add-in for Visual Studio 2012. For information and download links, visit Scott Hanselmans blog:

http://www.hanselman.com/blog/GitSupportForVisualStudioGitTFSAndVSPutIntoContext.aspx

When you have downloaded and installed everything you need to open up Visual Studio and clone the repository which you can find at:

git://github.com/Polymer/polymer.git

You should have all files needed now, and will be able to update them later on with just a click. :-)

Creating the <x-simplevideo /> element

Since we will use HTML Imports to include the custom element, we will need two different HTML files, index.html and x-simplevideo.html.

Note: You should always prefix your custom elements with ”x-” since you don´t want to risk problems with new elements in the specification further on (for example, we name our element <simplevideo />, and W3C decides to create their own <simplevideo /> in year 2018).

This is how our new element will work:

1 - DIagram

The custom element will be included with its own DOM since it´s a separate file. It will include a standard video control though, but we will replace the menu controls with our own menu.

To get started with the new element we will make it as simple as possible to start with. So let´s start with the X-simplevideo.html.

<element name="x-simplevideo">
    <template>
        <video controls src="Big_Buck_Bunny_Trailer_400p.ogg.360p.webm"></video>
    </template>
    <script>
        'use strict';
 
        Polymer.register(this);
    </script>
</element>

The ”element element” specifies our element. The name attribute is what we are going to use in the parent site (<x-simplevideo />). We are also going to add some other attributes here later. The next element is the template element. It contains what is going to be rendered by the browser, but since it´s part of our x-simplevideo element, it will be hidden in the Shadow DOM. The script tags outside of the template will never be rendered, and will only be used by our own element.

Since we need to use the Polymer polyfill to use all these new specifications, we will need to register our element.

The next step is to actually use the element on index.html.

<!DOCTYPE html>
<html>
<head>
    <title>SuperVideo</title>
    <script src="polymer.min.js"></script>
    <link rel="import" href="x-simplevideo.html">
</head>
<body>
    <h1>Simplevideo test</h1>
    
    <x-simplevideo />
</body>
</html>

First of all we need to import our element in the head of the page. As soon as it´s imported, we can start using it.

If we open the page now, we will see this:

2 - First video

And if we take a look at the DOM in Developer tools, we can see that there is no trace of our original video element, but only the custom element we created.

3 - Developer tools

Make it customizable with attributes

Our new videoplayer is a new element which can play a single video, nothing special about that. The next step is to make it more customizable, so the user of our new element can choose which video to play, and also change the width and height of the player.

The first thing we need to do is to add support for these new attributes:

<element name="x-simplevideo" attributes="src width height">

And now we need to register them so we can use them either by using JavaScript or by binding them directly to our videoplayer.

Polymer.register(this, {
    src: '',
    width: '480',
    height: '400'
});

As you can see we have some standard values in case the user didn´t specify them. The last step is to bind these attributes to the videoplayer.

<video controls src="{{src}}" width="{{width}}" height="{{height}}"></video>

Now when we use the player in index.html, we can specify these three attributes.

<x-simplevideo src="Big_Buck_Bunny_Trailer_400p.ogg.360p.webm" width="500" height="300" />

If we play the video again, it is playing the same video, but has changed size to 500x300 pixels.

Add custom menu controls

What we have now is still the standard video control, but what we want is to use our own menu control instead of the original one. To do this, we first need to remove the controls attribute from the video element. Now we will add a really simple menu with play, pause and a timeline.

<element name="x-simplevideo" attributes="src width height">
    <template>
        <style scoped>
            div {
                display: inline-block;
                position: relative;
            }
 
            nav {
                background: rgba(0, 187, 255, 0.5);
                top: 0;
                opacity: 0.1;
                position: absolute;
                transition: all 0.5s;
                width: 100%;
            }
 
            video:hover ~ nav, nav:hover {
                opacity: 1;
            }
        </style>
        <div>
            <video src="{{src}}" width="{{width}}" height="{{height}}" id="video"></video>
            <nav>
                <input type="button" on-click="playVideo" value="Play" />
                <input type="button" on-click="pauseVideo" value="Pause" />
                <input type="range" name="timeline" max="{{videoDuration}}" value="{{currentTime}}" id="timeline" />
            </nav>
        </div>
    </template>
    <script>
        'use strict';
 
        Polymer.register(this, {
            src: '',
            width: '480',
            height: '400',
            videoDuration: 0,
            currentTime: 0,
            playVideo: function () {
                this.$.video.play();
            },
            pauseVideo: function () {
                this.$.video.pause();
            },
            srcChanged: function () {
                (function (scope, video) {
 
                    scope.$.video.addEventListener('canplay', function () {
                        scope.videoDuration = scope.$.video.duration;
                    });
 
                    scope.$.video.addEventListener('timeupdate', function () {
                        scope.currentTime = video.currentTime;
                    });
 
                })(this, this.$.video);
            }
        });
    </script>
</element>

Some new things have happened now. First, we have added styling for the menu element. Then we have added and id to the video element so we can use it with the Polymer API. The video element is now encapsulated inside a div together with the nav element which is used as menu control. Last, we have added new properties for duration and current time, and some functions that we use for play, pause and to update the properties when the video src is updated.

For the play and pause buttons, on-click attributes are added. These are used by Polymer to bind the click event to functions specified in Polymer.register().

All properties registered in Polymer is having observers, such as srcChanged, which will listen for changes in that specific property. When the value changes, we update videoDuration and currentTime, which will reflect the changes to our menu control automatically.

We have also binded videoDuration to our range element, so the value will be updated while we are playing the movie, and also let us go back and forward in the video.

If we reload the page with these changes and play the video, we will now get this:

4 - Menu control

It´s not the most elegant video player, but it was easy to create, and even more easier to reuse. All we have to do is to import the x-simplevideo element and add the element on our page. All HTML, CSS and JavaScript will be used only in that specific element, so it´s really simple to distribute these components to other sites. If we open Developer tools, we can see that we still only have our x-simplevideo element in the DOM, while the rest is hidden in the Shadow DOM.

In DOM Level 3 Events, a new type of events, CustomEvent, is available. It extends the ordinary Event with a new detail property which you can use to provide extra information. With this new method you are able to create new types of events that you can use in your application.

To use the event, you use addEventListener, just as you do with click, mouseover, load etc. But instead of using those events that you are used to, you can name your event whatever you want, and then add a listener to any element on your page.

To start with, we need to have a web page:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>Lab - CustomEvent</title>
</head>
<body>
    <h1>CustomEvent</h1>
 
    <div id="content">Lorem ipsum...</div>
 
    <input type="button" id="magic" value="Click me!" />
 
    <script src="scripts/customevents.js"></script>
</body>
</html>

The idea is that when we click on the button, I want to trigger a custom event that I have created, and which the div element (#content) is listening to.

The first thing we need now is to create the CustomEvent.

var customEvent = new CustomEvent('doMagic', {
    detail: {
        message: 'Click #'
    }
});

customEvent is now a new instance of CustomEvent, which we can add listeners for. When the event is triggered, it will automatically call all event listeners and send not just the normal properties, it will also send detail.message in this case. The detail property is just a normal object, so we can add all data we think is useful there.

The next step is to listen for changes, so we will add a new listener to the content element.

var contentBox = document.getElementById('content');
var count = 0;
 
contentBox.addEventListener('doMagic', function (e) {
    count++;
    this.textContent = e.detail.message + count;
}, false);

Nothing strange here. When we trigger the doMagic event, we want to execute the function in the event listener, which will change the textContent in our div to the message that was sent to us, and apply the number of calls to the method.

The last step is to actually trigger the event.

var magicButton = document.getElementById('magic');
 
magicButton.addEventListener('click', function () {
    contentBox.dispatchEvent(customEvent);
}, false);

I am listening for clicks on the button, and then trigger doMagic using the dispatchEvent method and send in the reference to the CustomEvent.

Custom events like this can be really useful, for example when building different controls where the developer using your control should be able to listen for specific changes, like folding out a dropdown menu. Libraries such as jQuery has this functionality built in already, but now you can listen for events in a standardized way using almost no extra code at all.

So what about browser compatibility? Actually, almost all modern browsers supports everything here (Chrome 15, Firefox 11, Opera 11.60 and Nightly builds of Safari according to MDN). IE 9 supports everything except from the use of the constructor, which is part of DOM Events Level 4. Take a look at the MSDN page for more information about support in IE. If you use the functionality as specified in the DOM Events Level 3 specification, all major browsers will be able to run your code.

You can find more info about this at:

In the upcoming specification for HTML 5.1, a new semantic element will be introduced, the <main> element.

When developing web sites using HTML5 you might be using the new semantic elements such as <article>, <section>, <aside>, <nav> etc. They are great for marking different sections of your content, but none of them is telling the user which content is specific for the current page.

Let´s say your layout looks like this:

1 - Layout

The content in the “main container” is what is unique for that page. The header and the context boxes on the right are static and will look the same on all pages.

The markup for this page might look like something like this:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>My awesome site!</title>
</head>
<body>
    <header>
        <h1>My awesome site</h1>
    </header>
    <div id="main" role="main">
        <article>
            <!-- Markup for the article -->
        </article>
        <section>
            <!-- Comments -->
        </section>
    </div>
    <section>
        <!-- Content boxes with addition information -->
    </section>
    <footer>
        Copyright &copy; 2013 Foo Bar Inc, all rights reserved.
    </footer>
</body>
</html>

Here we use the div element to mark our main content. We also have the main role for accessibility purposes.

But instead of using this div element, HTML 5.1 will allow us to use the main element, which will look like this:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>My awesome site!</title>
</head>
<body>
    <header>
        <h1>My awesome site</h1>
    </header>
    <main role="main">
        <article>
            <!-- Markup for the article -->
        </article>
        <section>
            <!-- Comments -->
        </section>
    </main>
    <section>
        <!-- Content boxes with addition information -->
    </section>
    <footer>
        Copyright &copy; 2013 Foo Bar Inc, all rights reserved.
    </footer>
</body>
</html>

It looks almost the same, but we use the main element instead of the div, which gives us more semantic HTML. Since no user agents supports the main element yet, we should still have the role attribute set to main. When more user agents supports this element we could skip this though.

There are some important things you as a developer must know about this element though:

  • You can only have one main element on each page.
  • You must only use it for the page specific content. Don´t use it for your page header for example.
  • You must not use the main element as a child of an article, aside, footer, header or nav element.

Except from these cases, you are good to go! Since all modern web browsers will ignore this element, you can actually use it today. To be able to style it in IE 8 or earlier, you will have to create the element using JavaScript.

When you add an element to your page, it is being added to the Document Object Model (DOM). When added to the DOM, you can use CSS to style it or JavaScript (getElementById, querySelector etc) to get a reference to the element and modify it. There are some cases where this isn´t true though.

Let´s say we want to add a video player to our site. We use the standard <video> element, choose which movie to play and start it. Here we have a standard element doing what it´s supposed to do. But what if we add the controls attribute?

This is what we see in the browser if we are using Internet Explorer 10:

1 - video

We have got some controls here as expected since we added the controls attribute. BUT..! Where are they in the DOM? If we take a look at the Developer Tools in IE 10 we will see this:

2 - dev tools

As we can see in the picture above, there are no elements for the play/pause button, the time slider or the other elements. So where are they?

The answer to that question is the Shadow DOM.

To make it easier to explain how it works I have created this diagram with the current DOM:

3 - diagram

The blue elements are what we can see in the DOM through Developer Tools, and the green elements are what is hidden in the Shadow DOM.

So…

Okay, so there is this thing Shadow DOM… But… What does it matter to me as a web developer? If it´s hidden, why would I care about it?

Thanks to a new specification on W3C, called Web Components, we can actually use Shadow DOM to create components that will be visible for the user, but rendered separately from the rest of the page. This means we can use HTML, CSS and JavaScript that is rendered independently from what is being rendered for the rest of the page.

At the moment, there is only one browser that supports Web Components, and that is Chrome Canary (Chrome 25), so I will be using it for the demos.

Creating a Shadow Host using JavaScript

First of all we will need to create a new HTML document. I have created a very simple one which looks like this:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Creating a Shadow Host using JavaScript</title>
        <style>
            p { color: #0a0; }
        </style>
    </head>
<body>
    <h1>
        Shadow DOM
    </h1>
    <p>This is rendered outside of our Shadow DOM.</p>
    
    <div id="shadowhost"></div>
</body>
</html>

The div element with id “shadowhost” will be the host for our Shadow DOM Tree. The first we will have to do is to create a new Shadow DOM based on that element using JavaScript.

Let´s add these three lines of JavaScript:

var el = document.querySelector('#shadowhost');
var root = el.webkitCreateShadowRoot();
root.innerHTML = '<p>Rendered inside of our Shadow DOM!</p>';

The first thing we are doing here is to get a reference of the div element which will be the host. After that we use the webkitCreateShadowRoot method (when more browsers have support for this you will of course have to use their vendor specific prefixes as well, but for the moment I will only use webkit to save some lines). The next step is to add a p element to the div.

This is no rocket science, and you have probably used the code before (except from the second line). But it is the second line which is creating the magic.

If we take a look at the page in Chrome Canary, we will get this result:

4 - Chrome

Whoa! Two things are different from how we are used to see things when we are adding elements.

  1. We added a p element, and we have CSS that is supposed to make the text green, as in the first p element on the page.
  2. Our shadowhost is still empty! Where is the p element we added and which is apparently added to the page?

First of all, the text is black since our shadow tree is like a whole new document, as if we would have added an iframe. The difference here is that it is on the same page. It is in other words not affected by the surrounding DOM.

And the reason to why we can´t see the element in the DOM is because there are no elements in the DOM, since they are in the Shadow DOM.

Light up the Shadow DOM

In Chrome Developer Tools, there is actually possible to show the Shadow DOM. If we go to settings –> General and active “Show Shadow DOM” we will be able to see what´s inside of the Shadow DOM.

And what about the CSS? You might want the developer using your component to be able to style the elements inside of your Shadow DOM. This is actually possible by enabling applyAuthorStyles for the root variable:

root.applyAuthorStyles = true;

With “Show Shadow DOM” enabled in the Developer Tools, and applyAuthorStyles set to true, we will get this result:

5 - Chrome

Great! We are now able to add elements that are not (usually) visible in the DOM Tree, and we can choose whether or not our elements will be affected by the styles set by the developer who will be using our component.

Create a separate HTML file for the component

So far, we have been using pure JavaScript and an empty element on the page for our component. But this isn´t probably the most usable way to use it all times. Sometimes you would want to create a separate HTML file for the component which contains all styles, data etc that you would want to use for your component, and later on give the user of your component the ability to add it to their page for a better experience.

The next step here is to create an entirely new HTML page. In this page we will use some new elements; <element>, <template> and <content>, as well as some new attributes to use with them.

But first of all we have to create the document which will be visible for the user, where we will use the component:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Shadow DOM</title>
    <link rel="components" href="vip-component.html" />
</head>
<body>
    <h1>Persons</h1>
    <ul is="vips">
        <li class="vip">Mikael Söderström</li>
        <li>Boris Jeltsin</li>
        <li>Julius Caesar</li>
        <li class="vip">Bill Gates</li>
    </ul>
    <script src="scripts/components-polyfill.js"></script>
</body>
</html>

We have a list with people here, and on two of them we have the vip class (hrm ;-)). In the head you can see something different though. We have a link element that references to a vip-component.html as “components”. In the vip-component.html page we will use markup to create our Shadow DOM, and then apply it on the list. Since all features aren´t implemented in the browser yet, we will have to include a polyfill as well.

You can download the polyfill here:

https://github.com/dglazkov/Web-Components-Polyfill

If we open the page we will see nothing but a list with names, so the next step is to create the vip-component.html page which will look like this:

 

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>
    <element name="vips" extends="ul">
        <template>
            <h2>VIP</h2>
            <div>
                <ul>
                    <content select=".vip"></content>
                </ul>
            </div>
            
            <h2>Other people</h2>
            <div>
                <ul>
                    <content></content>
                </ul>
            </div>
        </template>
    </element>
</body>
</html>

It looks like an ordinary HTML page, but we are using some new elements that is supported by the Web Components API.

  • <element> is the name of our new element, and in this case we are extending the existing ul element. We could create a whole new <vip> element if we want to.
  • <template> tolds the browser that this is the template which will be rendered in the Shadow DOM.
  • <content> is where the markup will be placed from the original DOM. The select attribute uses ordinare CSS selectors, and in the first content element we want the users who have the class “vip”, and in the other content element we will have the rest.

To test this, I disabled “Show Shadow DOM” in the Chrome Developer Tools and reloaded the page. This is what I got:

6 - Chrome

If we look at the DOM, we still have the original one as before, but if we look at the page, we can see that we have the grouping and headers from our Web Component!

Conclusion

Web Components are extremely useful in a lot of cases where you want to separate your components into other files, and at the same time let them be isolated from CSS in your original page.

I  just demonstrated the basics here, but if you want to go one step further, you could add JavaScript methods in your component, that the original page can call to modify your Shadow DOM, like the play() method on the video element. You can also add your own pseudo classes to the CSS for your element, like ul:vip-header { color: #0f0; } in this case.

Have you used Web Components and perhaps have any cool demos? Please let me know!

ASP.NET Web Pages Beta 1 have support for Helpers, which are methods written in C# or Visual Basic, and returns IHtmlString. They can return HTML that is displayed on the page. If you choose to create helpers that way, you would need to have your HTML in an assembly, which makes it different to modify. Because of that, the new version of Razor supports declarative Helpers that you can create directly on the page. They work in both ASP.NET MVC 3 Beta and ASP.NET Web Pages Beta 2, which is included in WebMatrix.

A declarative helper is created the same way as a method, but instead of having a return type, you set ”helper”.

Let´s say you have this code:

@{
    var text = "Hello, world!";
    <p>@text</p>
}

We want to refactor it into its own method to be able to reuse it. We can do it using a declative helper, like this:

@helper SayHello(string yadda)
{
    <p>Text: @yadda</p>
}

And if you want to use it:

@SayHello("Hello, world!")

We can also add code in the helper, such as:

@helper Calculator(int a, int b)
{
    @{
        var sum = a + b;
    }
    
    <b>@sum</b>
}

And to display the result, we use:

1 + 2 = @Calculator(1, 2)

It will display ”3” on the page, which is the sum of the numbers.

To go one step further and make it even more dynamic, we can use Lambda Expressions for the helper. If we want to be able to change how to count the result, we could use this instead:

@helper Calc(int a, int b, Func<int, int, int> calc)
{
    @{
        var sum = calc(a, b);
    }
    <p>@sum</p>
}

And if we want to multiply the letters, we use the helper this way:

@Calc(4, 4, (a, b) => a * b)

We can actually create really advanced helpers directly on the page. This is for those who are using ASP.NET Web Pages, but it can also be used in ASP.NET MVC 3 Beta.

In ASP.NET MVC 2 we got support for client validation of the model. When we activate it, a JavaScript is generated and added to the rendered view. It contains all validation rules we set up for the model, and are used to generate error massages without reloading the page.

I ASP.NET MVC 3 they have extended that support. Instead of generating a JavaScript, you can now use ”unobtrusive Jquery validation”, which uses the data-* attribute in HTML5 instead of using JavaScript.

To activate it on the page you can add this:

@Html.EnableUnobtrusiveJavaScript()

And to activate it on all pages, you can add a key to web.config:

<appSettings>
  <add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>

New ASP.NET MVC 3 Beta projects will have this enabled as default, and upgraded projects will not have it activated as default to make sure it is backwards compatible.

To use this new validation, you will have to add references to jquery-1.4.1.js, jquery.validate.js and jquery.validate.unobtrusive.js.

To test this, I have a model, ”Customer”, which looks like this:

using System;
using System.ComponentModel.DataAnnotations;
 
namespace MyMvc3Site.Models
{
    public class Customer
    {
        [Required]
        public int CustomerId { get; set; }
 
        [Required]
        [StringLength(5)]
        public string Name { get; set; }
 
        [Required]
        public DateTime Birthday { get; set; }
    }
}

In the view, I have this:

@model MyMvc3Site.Models.Customer
 
@{
    View.Title = "Create";
}
 
<h2>Create</h2>
 
@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
 
    <fieldset>
        <legend>Fields</legend>
            
        <div class="editor-label">
            @Html.LabelFor(model => model.CustomerId)
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.CustomerId)
            @Html.ValidationMessageFor(model => model.CustomerId)
        </div>
            
        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>
            
        <div class="editor-label">
            @Html.LabelFor(model => model.Birthday)
        </div>
        <div class="editor-field">
            @Html.TextBoxFor(model => model.Birthday)
            @Html.ValidationMessageFor(model => model.Birthday)
        </div>
            
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
 
}

Without unobtrusive jQuery validation, we will get this in the view:

<form action="/Customer/Create" id="form0" method="post"><div class="validation-summary-valid" id="validationSummary"><ul><li style="display:none"></li>
</ul></div>    <fieldset>
        <legend>Fields</legend>
            
        <div class="editor-label">
            <label for="CustomerId">CustomerId</label>
        </div>
        <div class="editor-field">
            <input id="CustomerId" name="CustomerId" type="text" value="" />
            <span class="field-validation-valid" id="CustomerId_validationMessage"></span>
        </div>
            
        <div class="editor-label">
            <label for="Name">Name</label>
        </div>
        <div class="editor-field">
            <input id="Name" name="Name" type="text" value="" />
            <span class="field-validation-valid" id="Name_validationMessage"></span>
        </div>
            
        <div class="editor-label">
            <label for="Birthday">Birthday</label>
        </div>
        <div class="editor-field">
            <input id="Birthday" name="Birthday" type="text" value="" />
            <span class="field-validation-valid" id="Birthday_validationMessage"></span>
        </div>
            
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
</form><script type="text/javascript">
//<![CDATA[
if (!window.mvcClientValidationMetadata) { window.mvcClientValidationMetadata = []; }
window.mvcClientValidationMetadata.push({"Fields":[{"FieldName":"CustomerId",
"ReplaceValidationMessageContents":true,"ValidationMessageId":"CustomerId_validationMessage",
"ValidationRules":[{"ErrorMessage":"The CustomerId field is required.","ValidationParameters":{},
"ValidationType":"required"},{"ErrorMessage":"The field CustomerId must be a number.",
"ValidationParameters":{},"ValidationType":"number"}]},{"FieldName":"Name",
"ReplaceValidationMessageContents":true,"ValidationMessageId":"Name_validationMessage",
"ValidationRules":[{"ErrorMessage":"The Name field is required.","ValidationParameters":{},
"ValidationType":"required"},{"ErrorMessage":"The field Name must be a string with a maximum length of 5.",
"ValidationParameters":{"max":5},"ValidationType":"length"}]},{"FieldName":"Birthday",
"ReplaceValidationMessageContents":true,"ValidationMessageId":"Birthday_validationMessage",
"ValidationRules":[{"ErrorMessage":"The Birthday field is required.","ValidationParameters":{},
"ValidationType":"required"}]}],"FormId":"form0","ReplaceValidationSummary":false,"ValidationSummaryId":"validationSummary"});
//]]>
</script>

It is a lot of JavaScript being rendered, and if we activate unobtrusive jQuery validation, we will get this instead:

<form action="/Customer/Create" method="post">    <fieldset>
        <legend>Fields</legend>
            
        <div class="editor-label">
            <label for="CustomerId">CustomerId</label>
        </div>
        <div class="editor-field">
            <input data-val="true" data-val-number="The field CustomerId must be a number." data-val-required="The CustomerId field is required." id="CustomerId" name="CustomerId" type="text" value="" />
            <span class="field-validation-valid" data-valmsg-for="CustomerId" data-valmsg-replace="true"></span>
        </div>
            
        <div class="editor-label">
            <label for="Name">Name</label>
        </div>
        <div class="editor-field">
            <input data-val="true" data-val-length="The field Name must be a string with a maximum length of 5." data-val-length-max="5" data-val-required="The Name field is required." id="Name" name="Name" type="text" value="" />
            <span class="field-validation-valid" data-valmsg-for="Name" data-valmsg-replace="true"></span>
        </div>
            
        <div class="editor-label">
            <label for="Birthday">Birthday</label>
        </div>
        <div class="editor-field">
            <input data-val="true" data-val-required="The Birthday field is required." id="Birthday" name="Birthday" type="text" value="" />
            <span class="field-validation-valid" data-valmsg-for="Birthday" data-valmsg-replace="true"></span>
        </div>
            
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
</form>

Instead of JavaScript, the different elements will have a couple of new attributes instead. Jquery.validation.unobtrusive.js contains functionality that can parse these values and generates error messages based on these instead. In this way, we will get much cleaner HTML, and still have valid HTML5. The validation will work exactly like before, the only difference is what is being rendered.

When you install ASP.NET MVC 3 Beta or WebMatrix Beta 2, a new product called ”NuPack” is installed with it. NuPack makes it possible to quickly add references to third party products like Ninject, jQuery and so on. All necessary files (dll, js etc) are automatically added to the project, and necessary modifications in web.config are automatically added.

There is an existing list with packages that is used when installing NuPack, but you can create your own if you need to. You can also put all packages on a network share so you can distribute them to all developers at your company.

I am going to show you how to add packages in both Visual Studio and WebMatrix since they work differently.

NuPack in Visual Studio 2010

In Visual Studio, we have to different ways to add references, in the GUI or through a Console window, which is based on PowerShell.

In the GUI, we can get a list with all products, add them to the project and update existing references. In the console window, we can do the same, but also remove existing references.

NuPack works in both existing projects, and in new projects. I have now created a new ASP.NET MVC 3 project with no references at all. To be able to log all errors, I would like to add ELMAH, which is a really good tool that can be used to log all errors. If I was going to add it manually, I would have to go to the homepage, download the assembly, add a reference to the assembly and then make some changes in web.config. If I want to use NHibernate or some other tools, I will have to do the same with them and all dependencies.

Instead of doing this manually, I will use NuPack to add ELMAH to my project.

To add ELMAH, I right-click on References in my project, and then I click on “Add Package Reference”. This window is now opened:

mvc-1-modal

I search for ELMAH and choose to install it. What happens now is that ELMAH is downloaded and added as a reference in the project, and all necessary modifications in web.config are automatically done!

If we take a look in the folder where we have our solution, there is a new folder named ”packages”, and here we can find ”elmah 1.1” which contains all files we just downloaded. We have also got a new file in our project, “packages.config”, which contains the name and version of the package.

This took a few seconds to do, which is going to save us a lot of time compared to doing this manually (downloading files, adding references, reading instructions etc).

We also have a concole window for NuPack, which can be used the same way.

mvc-2-console

We can use commands like:

· Add-Package name – Adding the package ”name”

· Remove-Package name – Removing the package ”name”

· List-Package – Displays a list with all packages

· Update-Package name – Updating the package ”name” to the latest version

If we want to remove ELMAH, which we just added we can write:

Remove-Package ELMAH

All references are deleted, and the changes in web.config are restored.

If we install MvcScaffold we will get new PowerShell commands to use, such as Add-MvcView, which adds a new view to the project.

ASP.NET Web Pages

If we want to use NuPack with ASP.NET Web Pages, we can use a website instead.

If we want to display the site, go to /_Admin in the browser. The first time we go here, we will have to set the admin password:

wm1-Admin

When we have entered the password, we will get to the next step where we can see a list with all available packages:

wm2-packages

The packages available for ASP.NET Web Pages contain different helpers, such as a Bing-helper which can be used to search on our site using Bing. There are also some other helpers here. If we choose to install Microsoft-web-helpers 1.0, the package will be downloaded and we will get this:

wm3-binginstalled

We can now use the helper on our site by writing:

@Bing.SearchBox(”http://www.minsida.com”)

This is the result:

wm4-searchbox

The first time we logged in on the site, we had to create a password. This password is hashed and then saved in a text file on the server:

wm5-Passwordtxt

It may look bad and insecure to store it in clear text, but you can´t actually open that file in the browser:

wm6-hiddensegment

Summary

Thanks to NuPack, we can quickly and easy add functionality to our site without doing anything but click on some buttons. Since we can create our own packages, we can use it internally on the company to easily distribute assemblies and settings to our colleagues.

Microsoft just released ASP.NET MVC 3 Beta, which came with some news. Among other things, we now have a new project dialog box, an updated version of Razor, support for helpers from ASP.NET Web Pages, new interfaces for Dependency Injection, unobtrusive jQuery validation and more. A new beta of WebMatrix has also been released.

New project dialog

When we created new ASP.NET MVC project in CTP's that came before, there were different project types for the Web Forms and Razor syntax. In ASP.NET MVC Beta we have a single project type called ASP.NET MVC 3 Web Application. If we choose to create a new project, we get a new window, where we can choose View Engine, type of ASP.NET MVC 3-projects and if we want a test project:

1-newproject

Updated version of Razor

Unfortunately, we still don´t have syntax highlighting and intellisense for Razor, but for syntax highlighting, you can use either WebMatrix, or this plugin for Visual Studio 2010:

http://bit.ly/a0Jkqv

However, there are some new features for Razor in ASP.NET MVC 3, like a new way to specify the model, as well as support for declarative helpers.

Helpers from ASP.NET Web Pages

When ASP.NET Web Pages came with WebMatrix, we got a couple of different helpers like one which is used to show a table, with support for sorting and paging. It can now be used in asp.net MVC 3.

New interfaces for Dependency Injection

ASP.NET MVC 3 CTP came with enhanced support for Dependency Injection, by IMvcServiceLocator. In the new beta, we can use the IDependencyResolver insttead, which is smaller and contains just what we need to inject code in ASP.NET MVC.

There is also a new interface called IControllerActivator, which is used to create an instance of an already existing instance of a controller, i.e. as that the Activator class. Unlike the IControllerFactory it is not used to locate the correct controller.

Unobtrusive jQuery Validation

ASP.NET MVC 2 supports validation on the client. In ASP.NET MVC 3 Beta has been updated to provide a cleaner way to validate. Instead of the JavaScript with validation rules directly on the page it now takes advantage of the data-* attribute from HTML5 on the elements. This means that the rendered HTML looks much better, while we still have a validated page (if we validate against HTML5). However, developers can disable it if they want to continue to use the JavaScript as before.

Updated ValidateInputAttribute

When we try to post HTML from the client, we will, by default, get an error message that says that potentially dangerous code has been posted. This came in ASP.NET 1.1, and can be turned off in WebForms by setting the ValidateRequest to false.

In ASP.NET MVC, we instead insert a ValidateInput attribute on the controller or action method and set the parameter to false. What´s new in ASP.NET MVC 3 Beta and WebMatrix Beta 2 is that we now can define specific fields you may post HTML, while all others are protected. This provides increased security when we usually do not want to allow HTML in all fields.

NuPack

A very exciting new feature, and which are included in both ASP.NET MVC 3 Beta and WebMatrix Beta 2 is NuPack. It is a new package manager which makes it possible to download and install modules with just a few clicks. This means that we can get the Ninject, jQuery, ELMAH, and more without having to go to each page and download them manually.

With ASP.NET MVC 3 Beta, we can either use a dialog window in Visual Studio to add packages, or we can use a new command window. With WebMatrix we visit a specific page instead to get access to the modules.

More information

I will mention all the new features in separate blog posts for more in-depth information, but you can already download both ASP.NET MVC 3 and WebMatrix here:

http://www.microsoft.com/web/gallery/install.aspx?appid=MVC3

More Posts Next page »