一、本样例中涉及到的一些知识点如下。
- 在HTML页面结构中,常用到的几个区域是头部区域,使用header元素;导航区域,使用nav 元素;在内容区域可以使用article元素来展示每一页的内容。这些标签元素都是HTML5标签。
- 在使用HTML5元素时,建议在文档的<head>元素中包含Modernizer库,用来对浏览器是否支持H5标签进行检验。
- 取得当前页面的URL,可以使用window.location.href 。
- HTML DOM中的每个表单元素都是一个form对象,每个form对象都有一个form.elements.length属性,需要注意的是这个属性返回的是表单中包含的表单元素的个数(不等同的所包含的节点个数)。element.value可得到表单元素的当前值。
- 在通过POST请求发送数据时,需要将表单中每个字段的值都编码为数据字符串(name=value&name2=value2),是使用javascript的encodeURIComponent函数把这些值编码成URL安全的字符串。这会把有歧义的字符转换为对应的ASCII编码。
- var matches = request.responseText.match(/<article>([\s\S]+)<\/article>/); 正则中使用了捕获组的定义。匹配结果是一个数组,第一个数组元素是与整个模式完整匹配的部分;匹配结果数组的第二个元素(索引为1),是responseText中与捕获组中的模式匹配的部分; 因为本例中只定义了一个捕获组,所以matches也只包含两个元素。
- request.readyState == 4 // 当访问请求处理完成,接收响应也完成后,才可满足左侧代码的等式
二、本样例中使用到的代码文件如下。
本样例实现后的效果图如下。
提供一个网络上的示例,不是基于最新版本的书籍实现的,但基本上95%是相同的。其中不同之处包括,未提供基于Ajax功能的函数实现。
1、模板文件template.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Jay Skript and the Domsters</title>
<script type="text/javascript" src="scripts/modernizr-1.6.min.js"></script>
<script type="text/javascript" src="scripts/global.js"></script>
<link rel="stylesheet" media="screen" href="styles/basic.css" />
</head>
<body>
<header>
<img src="images/logo.gif" alt="Jay Skript and the Domsters" />
<nav>
<ul>
<li><a href="index.html">Home</a></li>
<li><a href="about.html">About</a></li>
<li><a href="photos.html">Photos</a></li>
<li><a href="live.html">Live</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
</nav>
</header>
<article>
<h1>Lorem Ipsum Dolor</h1>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras varius accumsan tellus, in pulvinar lacus fermentum ut. Phasellus sem ante, rhoncus congue pellentesque a, pellentesque in purus. Aliquam in rutrum nulla. Nunc ut turpis a enim aliquam dapibus vitae scelerisque arcu. Ut condimentum nisi aliquet, molestie velit sed, aliquam arcu. Curabitur at est vel quam fringilla tincidunt. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque lobortis sed quam nec hendrerit. Proin dolor massa, pulvinar ut vestibulum ut, euismod vulputate diam. Quisque nec accumsan lacus, eu ullamcorper orci. Praesent condimentum feugiat vulputate. Suspendisse pulvinar, erat non finibus bibendum, erat urna dictum velit, nec pharetra magna mauris vel massa. Quisque sodales orci vitae ipsum rutrum, et ullamcorper leo posuere. Mauris dapibus ligula quam, nec pharetra ex porta nec. Mauris feugiat, nibh non varius tempus, massa turpis convallis risus, id tempor neque ante vel felis.
</p>
</article>
</body>
</html>
2、样式文件basic.css
@import url(layout.css);
@import url(color.css);
@import url(typography.css);
只包含了对另外三个样式文件的引用。
3、样式文件color.css
不管为哪个元素应用什么颜色,都要同时给它一个背景色。否则就有可能导致意外,看不到某些文本。
body {
color: #fb5;
background-color: #334;
}
a:link {
color: #445;
background-color: #eb6;
}
a:visited {
color: #345;
background-color: #eb6;
}
a:hover {
color: #667;
background-color: #fb5;
}
a:active {
color: #778;
background-color: #ec8;
}
header {
color: #ec8;
background-color: #334;
border-color: #667;
}
header nav {
color: #445;
background-color: #789;
border-color: #667;
}
article {
color: #223;
background-color: #edc;
border-color: #667;
}
header nav ul {
border-color: #99a;
}
header nav a:link,header nav a:visited {
color: #eef;
background-color: transparent;
border-color: #99a;
}
header nav a:hover {
color: #445;
background-color: #eb6;
}
header nav a:active {
color: #667;
background-color: #ec8;
}
article img {
border-color: #ba9;
outline-color: #dcb;
}
#imagegallery a {
background-color: transparent;
}
header nav a.here:link,
header nav a.here:visited,
header nav a.here:hover,
header nav a.here:active {
color: #eef;
background-color: #799;
}
tr.odd td {
color: #223;
background-color: #ec8;
}
tr.highlight td {
color: #223;
background-color: #cba;
}
th {
color: #edc;
background-color: #455;
}
tr td {
color: #223;
background-color: #eb6;
}
4、layout.css
首先是为HTML5块元素定义默认的样式,主要针对那些不支持它们的浏览器,好让这些元素都能具有适当的块布局。
其次,使用通配选择器把所有元素的内外边距都设置为零。这样就把不同浏览器为元素设置的不同的内外边距全都删除了。在重设这些值之后,所有样式就可以一视同仁了。
最终,我们使用自己的css定义颜色和布局。
layout.css中主要定义的是各种元素的内边距。
section, header, article, nav {
display: block;
}
* {
padding: 0;
margin: 0;
}
body {
margin: 1em 10%;
background-image: url(../images/background.gif);
background-attachment: fixed;
background-position: top left;
background-repeat: repeat-x;
max-width: 80em;
}
header {
background-image: url(../images/guitarist.gif);
background-repeat: no-repeat;
background-position: bottom right;
border-with: .1em;
border-style: solid;
border-bottom-width: 0;
}
header nav {
background-image: url(../images/navbar.gif);
background-repeat: repeat-x;
background-position: bottom left;
border-with: .1em;
border-style: solid;
border-bottom-width: 0;
border-top-width: 0;
padding-left: 10%;
}
header nav ul {
width: 100%;
overflow: hidden;
border-left-width: .1em;
border-left-style: solid;
}
header nav li {
display: inline;
}
header nav li a {
display: block;
float: left;
padding: .5em 2em;
border-right: .1em solid;
}
article {
border-width: .1em;
border-style: solid;
border-top-width: 0;
padding: 2em 10%;
line-height: 1.8em;
}
article img {
border-width: .1em;
border-style: solid;
outline-width: .1em;
outline-style: solid;
}
#about header {
background-image: url(../images/lineup.gif);
}
#photos header {
background-image: url(../images/basshead.gif);
}
#live header {
background-image: url(../images/bassist.gif);
}
#contact header {
background-image: url(../images/drummer.gif);
}
#slideshow {
width: 150px;
height: 150px;
position: relative;
overflow: hidden;
}
#preview {
position: absolute;
border-width: 0;
outline-width: 0
}
#frame {
position: absolute;
top: 0;
left: 0;
z-index: 99;
}
#imagegallery li {
display: inline;
}
dl {
overflow: hidden;
}
dt {
float: left;
}
dd {
float: left;
}
td {
padding: .5em 3em;
}
label {
display: block;
}
fieldset {
border: 0;
}
5、typography.css用来定义元素的外边距
body {
font-size: 76%;
font-family: "Helvetica","Arial",sans-serif;
}
body * {
font-size: 1em;
}
a {
font-weight: bold;
text-decoration: none;
}
header nav {
font-family: "Lucida Grande","Helvetica","Arial",sans-serif;
}
header nav a {
text-decoration: none;
font-weight: bold;
}
article {
line-height: 1.8em;
}
article p {
margin: 1em 0;
}
h1 {
font-family: "Georgia","Times New Roman",sans-serif;
font: 2.4em normal;
}
h2 {
font-family: "Georgia","Times New Roman",sans-serif;
font: 1.8em normal;
margin-top: 1em;
}
h3 {
font-family: "Georgia","Times New Roman",sans-serif;
font: 1.4em normal;
margin-top: 1em;
}
#imagegallery li {
list-style-type: none;
}
textarea {
font-family: "Helvetica","Arial",sans-serif;
}
dt {
margin-right: 1em;
}
dd {
margin-right: 3em;
}
6、最为重要的一个基础js函数global.js
在该js文件中将包含以下功能函数:
- addLoadEvent(func),设置随浏览器自动加载指定函数
- addClass(element,value),添加新的样式类
- insertAfter(newElement,targetElement),在指定元素后插入新元素
- highlightPage(href),突出当前页面链接的显示,同时为几个超链接页面的body元素添加id属性,以支持为每个页面应用不同的样式
- moveElement(elementID,final_x,final_y,interval),实现js动画效果的函数
- prepareSlideshow(),准备幻灯片元素并准备相应链接
- showSection(id),根据指定的id显示相应的<section>,同时隐藏其它部分
- prepareInternalnav(),在article元素中的nav所包含的链接被单击时调用showSection函数
- showPic(whichpic),在占位符位置上显示相应链接的图片
- preparePlaceholder(),创建和配置图片占位符
- prepareGallery(),创建和配置图片库
- stripeTables(),为表格增加斑马纹
- highlightRows(),高亮当前选择的行
- displayAbbreviations(),将缩略语显示为一个列表
- focusLabels(),点击label时自动将焦点定位到相应的表单元素上
- resetFields(whichform),重置表单元素初始值
- validateForm(whichform),表单元素检验函数
- isFilled(field),检验表单元素是否填写
- isEmail(field),检查是否是有效的邮件信息
- prepareForms(),设置和处理表单
- getHTTPObject(),获取一个XMLHttpRequest对象
- displayAjaxLoading(element),显示一个正在加载的图片
- submitFormWithAjax(whichform,thetarget),调用displayAjaxLoading函数,删除目标元素的子元素,并添加loading.gif图像;把表单的值组织成URL编码的字符串,以便通过Ajax请求发送;创建方法为POST的Ajax请求,把表单的值发送给submit.html; 如果请求成功,解析响应并在目标元素中显示结果; 如果请求失败,显示错误消息。
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}
}
}
function addClass(element,value) {
if (!element.className) {
element.className = value;
} else {
newClassName = element.className;
newClassName+= " ";
newClassName+= value;
element.className = newClassName;
}
}
function insertAfter(newElement,targetElement) {
var parent = targetElement.parentNode;
if (parent.lastChild == targetElement) {
parent.appendChild(newElement);
} else {
parent.insertBefore(newElement,targetElement.nextSibling);
}
}
// 突出当前页面链接的显示,同时为几个超链接页面的body元素添加id属性,以支持为每个页面应用不同的样式
function highlightPage(href) {
if (!document.getElementsByTagName) return false;
if (!document.getElementById) return false;
var headers = document.getElementsByTagName('header');
if (headers.length == 0) return false;
var navs = headers[0].getElementsByTagName('nav');
if (navs.length == 0) return false;
var links = navs[0].getElementsByTagName("a");
var linkurl;
for (var i=0; i<links.length; i++) {
linkurl = links[i].getAttribute("href");
// 将超链接的url和页面当前的url进行比较,以判定这个超链接是否属于当前页面
if (window.location.href.indexOf(linkurl) != -1) {
links[i].className = "here";
var linktext = links[i].lastChild.nodeValue.toLowerCase();
document.body.setAttribute("id",linktext);
}
}
}
addLoadEvent(highlightPage);
function moveElement(elementID,final_x,final_y,interval) {
if (!document.getElementById) return false;
if (!document.getElementById(elementID)) return false;
var elem = document.getElementById(elementID);
//在移动位置前先判断下元素的movement属性是否存在有效值,是则代表正在移动中
if (elem.movement) {
clearTimeout(elem.movement);
}
//判断下emem元素是否设置了元素位置的初始值,没有的话则主动指定一个
if (!elem.style.left) {
elem.style.left = "0px";
}
if (!elem.style.top) {
elem.style.top = "0px";
}
//因为接下来要基于位置进行计算,所以需要先转换为整数
var xpos = parseInt(elem.style.left);
var ypos = parseInt(elem.style.top);
var dist = 0;
//如果已经移动到目标位置,则退出并返回true
if (xpos == final_x && ypos == final_y) {
return true;
}
if (xpos < final_x) {
dist = Math.ceil((final_x - xpos)/10);
xpos = xpos + dist;
}
if (xpos > final_x) {
dist = Math.ceil((xpos - final_x)/10);
xpos = xpos - dist;
}
if (ypos < final_y) {
dist = Math.ceil((final_y - ypos)/10);
ypos = ypos + dist;
}
if (ypos > final_y) {
dist = Math.ceil((ypos - final_y)/10);
ypos = ypos - dist;
}
//设置elem元素的
elem.style.left = xpos + "px";
elem.style.top = ypos + "px";
//迭代调用函数自身,一直循环到满足函数开头的退出条件为止
var repeat = "moveElement('"+elementID+"',"+final_x+","+final_y+","+interval+")";
elem.movement = setTimeout(repeat,interval);
}
function prepareSlideshow() {
// 实现幻灯片功能
if (!document.getElementsByTagName) return false;
if (!document.getElementById) return false;
if (!document.getElementById("intro")) return false;
var intro = document.getElementById("intro");
var slideshow = document.createElement("div");
slideshow.setAttribute("id","slideshow");
var frame = document.createElement("img");
frame.setAttribute("src","images/frame.gif");
frame.setAttribute("alt","");
frame.setAttribute("id","frame");
slideshow.appendChild(frame);
var preview = document.createElement("img");
preview.setAttribute("src","images/slideshow.gif");
preview.setAttribute("alt","a glimpse of what awaits you");
preview.setAttribute("id","preview");
slideshow.appendChild(preview);
insertAfter(slideshow,intro);
var links = document.getElementsByTagName("a");
var destination;
for (var i=0; i<links.length; i++) {
links[i].onmouseover = function() {
destination = this.getAttribute("href");
if (destination.indexOf("index.html") != -1) {
moveElement("preview",0,0,5);
}
if (destination.indexOf("about.html") != -1) {
moveElement("preview",-150,0,5);
}
if (destination.indexOf("photos.html") != -1) {
moveElement("preview",-300,0,5);
}
if (destination.indexOf("live.html") != -1) {
moveElement("preview",-450,0,5);
}
if (destination.indexOf("contact.html") != -1) {
moveElement("preview",-600,0,5);
}
}
}
}
addLoadEvent(prepareSlideshow);
function showSection(id) {
// 根据指定id显示相应的section
var sections = document.getElementsByTagName("section");
for (var i=0; i<sections.length; i++ ) {
if (sections[i].getAttribute("id") != id) {
sections[i].style.display = "none";
} else {
sections[i].style.display = "block";
}
}
}
function prepareInternalnav() {
// 在article元素中的nav所包含的链接被单击时调用showSection函数
if (!document.getElementsByTagName) return false;
if (!document.getElementById) return false;
var articles = document.getElementsByTagName("article");
if (articles.length == 0) return false;
var navs = articles[0].getElementsByTagName("nav");
if (navs.length == 0) return false;
var nav = navs[0];
var links = nav.getElementsByTagName("a");
for (var i=0; i<links.length; i++ ) {
var sectionId = links[i].getAttribute("href").split("#")[1];
if (!document.getElementById(sectionId)) continue;
document.getElementById(sectionId).style.display = "none";
links[i].destination = sectionId;
links[i].onclick = function() {
showSection(this.destination);
return false;
}
}
}
addLoadEvent(prepareInternalnav);
function showPic(whichpic) {
if (!document.getElementById("placeholder")) return true;
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
placeholder.setAttribute("src",source);
if (!document.getElementById("description")) return false;
if (whichpic.getAttribute("title")) {
var text = whichpic.getAttribute("title");
} else {
var text = "";
}
var description = document.getElementById("description");
if (description.firstChild.nodeType == 3) {
description.firstChild.nodeValue = text;
}
return false;
}
function preparePlaceholder() {
if (!document.createElement) return false;
if (!document.createTextNode) return false;
if (!document.getElementById) return false;
if (!document.getElementById("imagegallery")) return false;
var placeholder = document.createElement("img");
placeholder.setAttribute("id","placeholder");
placeholder.setAttribute("src","images/placeholder.gif");
placeholder.setAttribute("alt","my image gallery");
var description = document.createElement("p");
description.setAttribute("id","description");
var desctext = document.createTextNode("Choose an image");
description.appendChild(desctext);
var gallery = document.getElementById("imagegallery");
insertAfter(description,gallery);
insertAfter(placeholder,description);
}
function prepareGallery() {
if (!document.getElementsByTagName) return false;
if (!document.getElementById) return false;
if (!document.getElementById("imagegallery")) return false;
var gallery = document.getElementById("imagegallery");
var links = gallery.getElementsByTagName("a");
for ( var i=0; i < links.length; i++) {
links[i].onclick = function() {
return showPic(this);
}
}
}
addLoadEvent(preparePlaceholder);
addLoadEvent(prepareGallery);
function stripeTables() {
if (!document.getElementsByTagName) return false;
var tables = document.getElementsByTagName("table");
for (var i=0; i<tables.length; i++) {
var odd = false;
var rows = tables[i].getElementsByTagName("tr");
for (var j=0; j<rows.length; j++) {
if (odd == true) {
addClass(rows[j],"odd");
odd = false;
} else {
odd = true;
}
}
}
}
function highlightRows() {
if(!document.getElementsByTagName) return false;
var rows = document.getElementsByTagName("tr");
for (var i=0; i<rows.length; i++) {
rows[i].oldClassName = rows[i].className
rows[i].onmouseover = function() {
addClass(this,"highlight");
}
rows[i].onmouseout = function() {
this.className = this.oldClassName
}
}
}
function displayAbbreviations() {
if (!document.getElementsByTagName || !document.createElement || !document.createTextNode) return false;
var abbreviations = document.getElementsByTagName("abbr");
if (abbreviations.length < 1) return false;
var defs = new Array();
for (var i=0; i<abbreviations.length; i++) {
var current_abbr = abbreviations[i];
if (current_abbr.childNodes.length < 1) continue;
var definition = current_abbr.getAttribute("title");
var key = current_abbr.lastChild.nodeValue;
defs[key] = definition;
}
var dlist = document.createElement("dl");
for (key in defs) {
var definition = defs[key];
var dtitle = document.createElement("dt");
var dtitle_text = document.createTextNode(key);
dtitle.appendChild(dtitle_text);
var ddesc = document.createElement("dd");
var ddesc_text = document.createTextNode(definition);
ddesc.appendChild(ddesc_text);
dlist.appendChild(dtitle);
dlist.appendChild(ddesc);
}
if (dlist.childNodes.length < 1) return false;
var header = document.createElement("h3");
var header_text = document.createTextNode("Abbreviations");
header.appendChild(header_text);
var container = document.getElementById("content");
container.appendChild(header);
container.appendChild(dlist);
}
addLoadEvent(stripeTables);
addLoadEvent(highlightRows);
addLoadEvent(displayAbbreviations);
function focusLabels() {
if (!document.getElementsByTagName) return false;
var labels = document.getElementsByTagName("label");
for (var i=0; i<labels.length; i++) {
if (!labels[i].getAttribute("for")) continue;
labels[i].onclick = function() {
var id = this.getAttribute("for");
if (!document.getElementById(id)) return false;
var element = document.getElementById(id);
element.focus();
}
}
}
function resetFields(whichform) {
for (var i=0; i<whichform.elements.length; i++) {
var element = whichform.elements[i];
if (element.type == "submit") continue;
if (!element.defaultValue) continue;
element.onfocus = function() {
if (this.value == this.defaultValue) {
this.value = "";
}
}
element.onblur = function() {
if (this.value == "") {
this.value = this.defaultValue;
}
}
}
}
function validateForm(whichform) {
for (var i=0; i<whichform.elements.length; i++) {
var element = whichform.elements[i];
if (element.className.indexOf("required") != -1) {
if (!isFilled(element)) {
alert("Please fill in the "+element.name+" field.");
return false;
}
}
if (element.className.indexOf("email") != -1) {
if (!isEmail(element)) {
alert("The "+element.name+" field must be a valid email address.");
return false;
}
}
}
return true;
}
function isFilled(field) {
if (field.value.length < 1 || field.value == field.defaultValue) {
return false;
} else {
return true;
}
}
function isEmail(field) {
if (field.value.indexOf("@") == -1 || field.value.indexOf(".") == -1) {
return false;
} else {
return true;
}
}
function prepareForms() {
for (var i=0; i<document.forms.length; i++) {
var thisform = document.forms[i];
resetFields(thisform);
thisform.onsubmit = function() {
if (!validateForm(this)) return false;
var article = document.getElementsByTagName('article')[0];
// 如果submitFormWithAjax函数成功发送了Ajax请求并返回true,则让submit事件处理函数返回false,以便阻止浏览器重复提交表单
if (submitFormWithAjax(this, article)) return false;
// 否则,说明submitFormWithAjax没有发送成功Ajax请求,因而让submit事件处理函数返回true,让表单像什么都没有发生一样继续通过页面提交
return true;
}
}
}
addLoadEvent(focusLabels);
addLoadEvent(prepareForms);
function getHTTPObject() {
if (typeof XMLHttpRequest == "undefined")
XMLHttpRequest = function () {
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
catch (e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
catch (e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP"); }
catch (e) {}
return false;
}
return new XMLHttpRequest();
}
function displayAjaxLoading(element) {
while (element.hasChildNodes()) {
element.removeChild(element.lastChild);
}
var content = document.createElement("img");
content.setAttribute("src","images/loading.gif");
content.setAttribute("alt","Loading...");
element.appendChild(content);
}
function submitFormWithAjax(whichform,thetarget) {
// 调用displayAjaxLoading函数,删除目标元素的子元素,并添加loading.gif图像
// 把表单的值组织成URL编码的字符串,以便通过Ajax请求发送
// 创建方法为POST的Ajax请求,把表单的值发送给submit.html
// 如果请求成功,解析响应并在目标元素中显示结果
// 如果请求失败,显示错误消息
var request = getHTTPObject();
if (!request) { return false; }
displayAjaxLoading(thetarget);
var dataParts = [];
var element;
for (var i=0; i<whichform.elements.length; i++) {
element = whichform.elements[i];
// 将表单元素拼成URL中传递的信息,同时对表单元素的值进行了适用于URL的转码
dataParts[i] = element.name + '=' + encodeURIComponent(element.value);
}
// 将数组内容拼接起来
var data = dataParts.join('&');
// 发起异步POST方式的访问
request.open('POST', whichform.getAttribute("action"), true);
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.onreadystatechange = function() {
// 当访问请求处理完成,接收响应也完成后
if (request.readyState == 4) {
if (request.status == 200 || request.status == 0) {
// 注意下面正则中使用了捕获组的定义
var matches = request.responseText.match(/<article>([\s\S]+)<\/article>/);
if (matches.length > 0) {
// 匹配结果是一个数组,第一个数组元素是与整个模式完整匹配的部分
// 匹配结果数组的第二个元素(索引为1),是responseText中与捕获组中的模式匹配的部分。
// 因为本例中只定义了一个捕获组,所以matches也只包含两个元素。
thetarget.innerHTML = matches[1];
} else {
thetarget.innerHTML = '<p>Oops, there was an error. Sorry.</p>';
}
} else {
thetarget.innerHTML = '<p>' + request.statusText + '</p>';
}
}
};
request.send(data);
return true;
};
关于谷歌浏览器会遇到的一个报错的说明:
Cross origin requests are only ! 。此为浏览器安全设置造成的,有解决方法但繁琐。建议此时使用一下其它浏览器进行测试即可。
其它页面文件:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Jay Skript and the Domsters</title>
<script type="text/javascript" src="scripts/modernizr-1.6.min.js"></script>
<script type="text/javascript" src="scripts/global.js"></script>
<link rel="stylesheet" media="screen" href="styles/basic.css" />
</head>
<body>
<header>
<img src="images/logo.gif" alt="Jay Skript and the Domsters" />
<nav>
<ul>
<li><a href="index.html">Home</a></li>
<li><a href="about.html">About</a></li>
<li><a href="photos.html">Photos</a></li>
<li><a href="live.html">Live</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
</nav>
</header>
<article>
<p id="intro">
Welcome to the official website of Jay Skript and the Domsters.
Here, you can <a href="about.html" title="About">learn more about the band</a>,
view <a href="photos.html" title="Photos">photos of the band</a>,
find out about <a href="live.html" title="Tour Date">tour dates</a>
and <a href="contact.html" title="Contact">get in touch with the band</a>.
</p>
</article>
</body>
</html>
about.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Jay Skript and the Domsters</title>
<script type="text/javascript" src="scripts/modernizr-1.6.min.js"></script>
<script type="text/javascript" src="scripts/global.js"></script>
<link rel="stylesheet" media="screen" href="styles/basic.css" />
</head>
<body>
<header>
<img src="images/logo.gif" alt="Jay Skript and the Domsters" />
<nav>
<ul>
<li><a href="index.html">Home</a></li>
<li><a href="about.html">About</a></li>
<li><a href="photos.html">Photos</a></li>
<li><a href="live.html">Live</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
</nav>
</header>
<article>
<h1>About the band</h1>
<nav>
<ul>
<li><a href="#jay">Jay Skript</a></li>
<li><a href="#domsters">The Domsters</a></li>
</ul>
</nav>
<section id="jay">
<h2>Jay Skript</h2>
<p>Jay Skript is going to rock your world!</p>
<p>Together with his compatriots The Domsters, Jay is set for world domination. Just you wait and see.</p>
<p>Jay Skript has been on the scene since the mid nineties. His talent hasn't always been recognized or fully appreciated. In the early days, he was often unfavorably compared to bigger, similarly-named artists. That's all in the past now.</p>
</section>
<section id="domsters">
<h2>The Domsters</h2>
<p>The Domsters have been around, in one form or another, for almost as long. It's only in the past few years that The Domsters have settled down to their current, stable line-up. Now they're a rock-solid bunch: methodical and dependable.</p>
</section>
</article>
</body>
</html>
photos.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Jay Skript And The Domsters: Photos</title>
<link rel="stylesheet" type="text/css" media="screen" href="styles/basic.css" />
<script type="text/javascript" src="scripts/global.js"></script>
</head>
<body>
<header>
<img src="images/logo.gif" alt="Jay Skript and the Domsters" />
<nav>
<ul>
<li><a href="index.html">Home</a></li>
<li><a href="about.html">About</a></li>
<li><a href="photos.html">Photos</a></li>
<li><a href="live.html">Live</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
</nav>
</header>
<article id="content">
<h1>Photos of the band</h1>
<ul id="imagegallery">
<li>
<a href="images/photos/concert.jpg" title="The crowd goes wild">
<img src="images/photos/thumbnail_concert.jpg" alt="the band in concert" />
</a>
</li>
<li>
<a href="images/photos/bassist.jpg" title="An atmospheric moment">
<img src="images/photos/thumbnail_bassist.jpg" alt="the bassist" />
</a>
</li>
<li>
<a href="images/photos/guitarist.jpg" title="Rocking out">
<img src="images/photos/thumbnail_guitarist.jpg" alt="the guitarist" />
</a>
</li>
<li>
<a href="images/photos/crowd.jpg" title="Encore! Encore!">
<img src="images/photos/thumbnail_crowd.jpg" alt="the audience" />
</a>
</li>
</ul>
</article>
</body>
</html>
live.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Jay Skript and the Domsters</title>
<script type="text/javascript" src="scripts/modernizr-1.6.min.js"></script>
<script type="text/javascript" src="scripts/global.js"></script>
<link rel="stylesheet" media="screen" href="styles/basic.css" />
</head>
<body>
<header>
<img src="images/logo.gif" alt="Jay Skript and the Domsters" />
<nav>
<ul>
<li><a href="index.html">Home</a></li>
<li><a href="about.html">About</a></li>
<li><a href="photos.html">Photos</a></li>
<li><a href="live.html">Live</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
</nav>
</header>
<article id="content">
<h1>Tour dates</h1>
<table summary="when and where you can see the band">
<thead>
<tr>
<th>Date</th>
<th>City</th>
<th>Venue</th>
</tr>
</thead>
<tbody>
<tr>
<td>June 9th</td>
<td>Portland, <abbr title="Oregon">OR</abbr></td>
<td>Crystal Ballroom</td>
</tr>
<tr>
<td>June 10th</td>
<td>Seattle, <abbr title="Washington">WA</abbr></td>
<td>Crocodile Cafe</td>
</tr>
<tr>
<td>June 12th</td>
<td>Sacramento, <abbr title="California">CA</abbr></td>
<td>Torch Club</td>
</tr>
<tr>
<td>June 17th</td>
<td>Austin, <abbr title="Texas">TX</abbr></td>
<td>Speakeasy</td>
</tr>
</tbody>
</table>
</article>
</body>
</html>
contact.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Jay Skript and the Domsters</title>
<script type="text/javascript" src="scripts/modernizr-1.6.min.js"></script>
<script type="text/javascript" src="scripts/global.js"></script>
<link rel="stylesheet" media="screen" href="styles/basic.css" />
</head>
<body>
<header>
<img src="images/logo.gif" alt="Jay Skript and the Domsters" />
<nav>
<ul>
<li><a href="index.html">Home</a></li>
<li><a href="about.html">About</a></li>
<li><a href="photos.html">Photos</a></li>
<li><a href="live.html">Live</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
</nav>
</header>
<article id="content">
<h1>Contact the band</h1>
<form method="post" action="submit.html">
<fieldset>
<p>
<label for="name">Name:</label>
<input type="text" id="name" name="name" value="Your name" class="required" />
</p>
<p>
<label for="email">Email:</label>
<input type="text" id="email" name="email" value="Your email address" class="email required" />
</p>
<p>
<label for="message">Message:</label>
<textarea cols="45" rows="7" id="message" name="message" class="required">Write your message here.</textarea>
</p>
<input type="submit" value="Send" />
</fieldset>
</form>
</article>
</body>
</html>
submit.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Jay Skript and the Domsters</title>
<script type="text/javascript" src="scripts/modernizr-1.6.min.js"></script>
<script type="text/javascript" src="scripts/global.js"></script>
<link rel="stylesheet" media="screen" href="styles/basic.css" />
</head>
<body>
<header>
<img src="images/logo.gif" alt="Jay Skript and the Domsters" />
<nav>
<ul>
<li><a href="index.html">Home</a></li>
<li><a href="about.html">About</a></li>
<li><a href="photos.html">Photos</a></li>
<li><a href="live.html">Live</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
</nav>
</header>
<article>
<h1>Thanks!</h1>
<p>
Thanks for contacting us.We'll get back to you as soon as we can.
</p>
</article>
</body>
</html>