了解 JavaScript (4)– 第一个 Web 应用程序
在下面的例子中,我们将要构建一个 Bingo 卡片游戏,每个示例演示 JavaScript 的不同方面,通过每次的改进将会得到最终有效的 Bingo 卡片。
Bingo 卡片的内容
美国 Bingo 卡片是 5 X 5 的方形,5 个列上标明 B-I-N-G-O,格子中包含 1~75 的数字。正中间是一个空格子,常常印着 free。每列可以包含的范围如下:
- B 列包含数字 1~15
- I 列包含数字 16~30
- N 列包含数字 31~45
- G 列包含数字 46~60
- O 列包含数字 61~75
原始1、第一个简单的 JavaScript 循环
bingo.html,这个页面建立 Bingo 卡片的框架。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Make Your Own Bingo</title>
<link rel="stylesheet" href="bingo.css">
<script src="bingo.js"></script>
</head>
<body>
<h1>Create A Bingo Card</h1>
<table>
<tr>
<th>B</th>
<th>I</th>
<th>N</th>
<th>G</th>
<th>O</th>
</tr> <tr>
<td id="square0"> </td>
<td id="square5"> </td>
<td id="square10"> </td>
<td id="square14"> </td>
<td id="square19"> </td>
</tr> <tr>
<td id="square1"> </td>
<td id="square6"> </td>
<td id="square11"> </td>
<td id="square15"> </td>
<td id="square20"> </td>
</tr> <tr>
<td id="square2"> </td>
<td id="square7"> </td>
<td id="free">Free</td>
<td id="square16"> </td>
<td id="square21"> </td>
</tr> <tr>
<td id="square3"> </td>
<td id="square8"> </td>
<td id="square12"> </td>
<td id="square17"> </td>
<td id="square22"> </td>
</tr> <tr>
<td id="square4"> </td>
<td id="square9"> </td>
<td id="square13"> </td>
<td id="square18"> </td>
<td id="square23"> </td>
</tr>
</table>
<p><a href="../111.html" id="reload">Click here</a> to create a new card</p>
</body>
</html>
bingo.css 为 Bingo 卡片添加样式
@charset "utf-8";
/* CSS Document */
body{
background-color: white;
color: black;
font-size: 20px;
font-family: "Lucida Console", Verdana, Arial, Helvetica, sans-serif;
} h1, th{
font-family: Georgia, "Times New Roman", Times, serif;
} h1 {
font-size: 28px;
} table{
border-collapse: collapse;
}
th, td{
padding: 10px;
border: 2px #666 solid;
text-align: center;
width: 20%;
} #free, .pickedBG{
background-color: #f66;
}
.winningBG{
background-image: url(redFlash.gif);
}
我们先看看上面的 HTML 和 CSS 页面,这个是 Bingo 卡片的框架,包含 6 行 5 列的表格,表格的第一行是BINGO字母,且第三行中间是一个 Free 表格,每个单元格都有一个 id 属性,脚本将使用此 id 操纵这些单元格内容。id 采用 square0、square1、square2,直到 square23 分布如下图,在页面的底部,有一个用来生成新卡片的链接。

我们将要用循环语句,最常用的就是 for 循环,这种循环使用一个计数器(counter),计数器是一个变量,它的初值是某个值。在测试条件得不到满足的时候就会结束。
我们将 bingo.html 中 <head> 标签中的 <script> 的 src 属性设置为 bingo01.js。
bingo01.js,使用 for 循环将表格内容填写为 1~75 中数,如下:
// JavaScript Document
window.onload = initAll; function initAll(){
for(var i=0; i<24; i++){
var newNum = Math.floor(Math.random() * 75) + 1;
document.getElementById('square' + i).innerHTML = newNum;
}
}
Math.random() 生成一个 0~1 的随机数,比如 0.123456789。然后与最大值(75)相乘,就会生成 0~75 之间的结果。对结果进行 Math.floor() 操作获得结果的整数部分。
该 bingo01.js 的显示结果如下:

第一个示例产生的卡片还不是有效的 Bingo 卡片,因为 Bingo 卡片对特定列有一些要求。后面的示例将对脚本进行改进,直到产生有效的 Bingo 卡片。
改进2、将值传递给函数
我们继续改进 bingo01.js,并保存为 bingo02.js,如下:
// JavaScript Document
window.onload = initAll; function initAll(){
for(var i=0; i<24; i++){
//我们将i值传递给 setSquare() 函数
setSquare(i);
}
} function setSquare(thisSquare){
var currSquare = "square" + thisSquare;
var newNum = Math.floor(Math.random() * 75) + 1;
document.getElementById(currSquare).innerHTML = newNum;
}
通过将值传递给 setSquare() 函数,使得脚本更加容易阅读和理解了。
改进3、探测对象
在编写脚本时,你可能希望检查浏览器是否有能力理解你要使用的对象。进行这种检查的方法称为对象探测(object detection)。如下:
if (document.getElementById){
如果对象存在,if 语句就为 true,脚本继续执行。但是如果浏览器不理解这个对象,就会返回 false,并执行条件语句 else 部分。
bingo03.js,增加了对象探测功能,如下:
// JavaScript Document
window.onload = initAll; function initAll(){
if(document.getElementById){
//如果 document.getElementById 这个对象存在的话
for(var i=0; i<24; i++){
setSquare(i);
}
}else{
alert('Sorry, your browser doesn\'t support this script!');
}
} function setSquare(thisSquare){
var currSquare = "square" + thisSquare;
var newNum = Math.floor(Math.random() * 75) + 1;
document.getElementById(currSquare).innerHTML = newNum;
}
改进4、处理数组
在这个示例中,我们将使用一个有用的 JavaScript 对象,数组(array)。
数组是一种可以存储一组信息的变量,与变量一眼个,可以使包含任何类型的数据。声明数组时,将数组元素放在括号中,以逗号分隔,如下:
var newCars = new Array("Toyota", "Honda", "Nissan");
在这个示例中,我们要确保 Bingo 卡片是仍然不是有效的,每列虽然具有不同的数字范围,但是一些列中出现重复的数字。
bingo04.js,这个脚本限制了每一列值的范围。
window.onload = initAll;
function initAll(){
if(document.getElementById){
for(var i=0; i<24; i++){
setSquare(i);
}
}else{
alert('Sorry, your browser doesn\'t support this script');
}
}
function setSquare(thisSquare){
var currSquare = 'square' + thisSquare;
var colPlace = new Array(0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4);
var colBasis = colPlace[thisSquare] * 15;
var newNum = colBasis + Math.floor(Math.random() * 15) + 1;
document.getElementById(currSquare).innerHTML = newNum;
}
该脚本执行后,显示如下:

改进5、处理有返回值的函数、运行时更新数组
我们将一些计算转移到一个函数中,这个函数为 Bingo 卡片上的单元格返回随机数,然后另一个函数使用它返回的结果,这使得整个更加容易理解了。
我们还要纠正一个问题, 避免出现重复的数字,在脚本运行时通过计算修改数组中的值。
bingo05.js,增加了一个 getNewNum 函数,返回一个 0~14 之间的数,新增了一个 usedNums 数组,存放 true / false ,主要是避免重复的数字。
// JavaScript Document
window.onload = initAll;
var usedNums = new Array(76); //已经初始化为 false function initAll(){
if(document.getElementById){
for(var i=0; i<24; i++){
setSquare(i);
}
}else{
alert("Sorry, your browser doesn't support this script");
}
} function setSquare(thisSquare){
var currSquare = 'square' + thisSquare;
var colPlace = new Array(0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4);
var colBasis = colPlace[thisSquare] * 15;
var newNum = colBasis + getNewNum() + 1;
//如果 usedNums[newNum] 为 true ,说明有重复数据,不做任何处理
if(!usedNums[newNum]){
usedNums[newNum] = true;
document.getElementById(currSquare).innerHTML = newNum;
} } function getNewNum(){
return Math.floor(Math.random() * 15);
}
脚本执行后,显示如下:

改进6、使用 do/while 循环
有时候,需要让代码循环许多次,但是无法确定需要循环多少次。在这种情况下,就要使用 do/while 循环,只要某个条件为 true, 就执行某种操作。
bingo06.js 脚本,在将数字放入单元格之前,首先检查是否已经使用了这个数字。如果这个数字已经使用过了,脚本就将生成新的随机数并重复该过程,直到找到不重复的数字为止,该脚本最终生成了有效的 Bingo 卡片。
// JavaScript Document
window.onload = initAll;
var usedNums = new Array(76); function initAll(){
if(document.getElementById){
for(var i=0; i<24; i++){
setSquare(i);
}
}else{
alert('Sorry, your browser doesn\'t support this script');
}
} function setSquare(thisSquare){
var currSquare = 'square' + thisSquare;
var colPlace = new Array(0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4);
var colBasis = colPlace[thisSquare] * 15;
var newNum; do{
newNum = colBasis + getNewNum() + 1;
}while (usedNums[newNum]);
//检查 usedNums[] 数组中 newNum 上的值,
//从而判断 newNum 是否已经使用过了 document.getElementById(currSquare).innerHTML = newNum;
}
脚本执行后,我们得到了有效的 Bingo 卡片,如下:

改进7、多种方式调用脚本
到目前为止,我们看到的脚本都是在加载页面的时候自动运行的。但是在显示环境中,常常希望用户对脚本有更多的控制能力,甚至允许他们控制脚本在何时运行。
bingo07.js 脚本中,允许我们通过页面底部的链接来重新运行脚本,这样就可以完全在浏览器中生成 Bingo 卡片,而不需要从服务器重新加载页面。这向用户提供了快速的响应,而且不会产生服务器负载。
// JavaScript Document
window.onload = initAll;
var usedNums = new Array(76); function initAll(){
if(document.getElementById){
document.getElementById("reload").onclick = anotherCard;
newCard();
}else{
alert("Sorry, your browser doesn't support this script");
}
} function newCard(){
for(var i=0; i<24; i++){
setSquare(i);
}
} function setSquare(thisSquare){
var currSquare = 'square' + thisSquare;
var colPlace = new Array(0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4);
var colBasis = colPlace[thisSquare] * 15;
var newNum; do{
newNum = colBasis + getNewNum() + 1;
}while(usedNums[newNum]) usedNums[newNum] = true;
document.getElementById(currSquare).innerHTML = newNum;
} function getNewNum(){
return Math.floor(Math.random() * 15);
} function anotherCard(){
for(var i=0; i<usedNums.length; i++){
usedNums[i] = false;
}
newCard();
return false;
//是浏览器不加载 href 中的链接地址
}
其实到了现在,你已经知道如何使用 JavaScript 进行重新加载一部分的页面了,而不需要向服务器请求整个页面,这正是 Ajax 的基本特色。
改进8、组合使用 JavaScript 和 CSS
该示例中我们将演示如何让用户能够操作所生成的 Bingo 卡片。
bingo08.js 脚本中我们将添加一些 JavaScript 来利用 CSS 的功能。
// JavaScript Document
window.onload = initAll;
var usedNums = new Array(76); function initAll(){
if(document.getElementById){
document.getElementById("reload").onclick = anotherCard;
newCard();
}else{
alert("Sorry, your browser doesn't support this script");
}
} function newCard(){
for(var i=0; i<24; i++){
setSquare(i);
}
} function setSquare(thisSquare){
var currSquare = 'square' + thisSquare;
var colPlace = new Array(0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4);
var colBasis = colPlace[thisSquare] * 15;
var newNum; do{
newNum = colBasis + getNewNum() + 1;
}while(usedNums[newNum]);
usedNums[newNum] = true;
document.getElementById(currSquare).innerHTML = newNum;
//确保 Bingo 卡片最初状态都是 class 属性都是空字符串
document.getElementById(currSquare).className = "";
//设置 每个 td 的 onmousedown 事件
document.getElementById(currSquare).onmousedown = toggleColor;
} function getNewNum(){
return Math.floor(Math.random() * 15);
} function anotherCard(){
for(var i=0; i<usedNums.length; i++){
usedNums[i] = false;
}
newCard();
return false;
} function toggleColor(evt){
//为了处理 IE 和 非IE 浏览器,如果是 非IE 则会有一个 evt 传递给函数
if(evt){
var thisSquare = evt.target;
}else{
//如果是 IE 浏览器 则必须通过下面的语句获得
var thisSquare = window.event.srcElement;
}
if(thisSquare.className == ""){
thisSquare.className = "pickedBG";
}else{
thisSquare.className = "";
}
/*
//自行通过 this 也可以获取当前元素进行修改,代码如下
if(this.className == ""){
this.className = "pickedBG";
}else{
this.className = "";
}
alert(this.className);
*/
}
脚本执行后,可以通过鼠标点击单元格,点击后的单元格背景变成红色,如下:

改进9、检查状态
用户能够给格子添加标记后,还可以检查格子是否构成了获胜模式。在下面的脚本中,用户选择那些已经被叫过的号码,bingo09.js 脚本会让用户知道什么时候他们获胜了,该脚本使用了复杂的数学计算来判断获胜组合。
// JavaScript Document
window.onload = initAll;
var usedNums = new Array(76); function initAll(){
if(document.getElementById){
document.getElementById("reload").onclick = anotherCard;
newCard();
}else{
alert("Sorry, your browser doesn't support this script");
}
} function newCard(){
for(var i=0; i<24; i++){
setSquare(i);
}
} function setSquare(thisSquare){
var currSquare = 'square' + thisSquare;
var colPlace = new Array(0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4);
var colBasis = colPlace[thisSquare] * 15;
var newNum;
do{
newNum = colBasis + getNewNum() + 1;
}while(usedNums[newNum]);
usedNums[newNum] = true;
document.getElementById(currSquare).innerHTML = newNum;
document.getElementById(currSquare).className = "";
document.getElementById(currSquare).onmousedown = toggleColor;
} function getNewNum(){
return Math.floor(Math.random() * 15);
} function anotherCard(){
for(var i=0; i<usedNums.length; i++){
usedNums[i] = false;
}
newCard();
return false;
} function toggleColor(evt){
if(evt){
var thisSquare = evt.target;
}else{
var thisSquare = window.event.srcElement;
}
if(thisSquare.className == ""){
thisSquare.className = "pickedBG";
}else{
thisSquare.className = "";
}
//此处增加 checkWin 函数,随时检查是否获胜
checkWin();
} function checkWin(){
//存储用户的获胜选项
var winningOption = -1;
//存储已经点击的格子
var setSquares = 0;
//存储获胜组合的数组
var winners = new Array(31, 992, 15360, 507904, 541729, 557328, 1083458, 2162820, 4329736, 8519745, 8659472, 16252928);
//检查每一个格子是否点击过
for(var i=0; i<24; i++){
var currSquare = "square" + i;
if(document.getElementById(currSquare).className != ""){
document.getElementById(currSquare).className = "pickedBG";
//按位运算,或 操作,记录用户点击的组合
setSquares = setSquares | Math.pow(2, i);
}
}
//与 操作,判断是否获胜
for(var i=0; i<winners.length; i++){
if((winners[i] & setSquares) == winners[i]){
winningOption = i;
//i就是用户获胜的状态
}
}
//如果是获胜者,则遍历每个格子,判断改格子是否获胜的格子
if(winningOption > -1){
for(var i=0; i<24; i++){
if(winners[winningOption] & Math.pow(2, i)){
currSquare = "square" + i;
document.getElementById(currSquare).className = "winningBG";
//winningBG 将设置背景为 GIF 动画
}
}
}
}
脚本执行后, 我们尝试选择对角线上格子,背景图案闪烁,说明获胜了,如下图:

改进10、处理字符串数组
到目前为止,我们所使用的数组都是由布尔值或者数字组成的,bingo10.js 脚本将演示使用字符串数组综合前面的所有技术,创建一个 Buzzword Bingo 游戏。
//buzzwords 数组至少需要24个元素
var buzzwords = new Array("Aggregate", "Ajax", "API", "Bandwidth", "Beta", "Bleeding edge", "Convergence", "Design pattern", "Disruptive", "DRM", "Enterprise", "Facilitate", "Folksonomy", "Framework", "Impact", "Innovate", "Long tail", "Mashup", "Microformats", "Mobile", "Monetize", "Open social", "Paradigm", "Podcast", "Proactive", "Rails", "Scalable", "Social bookmarks", "Social graph", "Social software", "Spam", "Synergy", "Tagging", "Tipping point", "Truthiness", "User-generated", "Vlog", "Webinar", "Wiki", "Workflow");
var usedWords = new Array(buzzwords.length);
window.onload = initAll; function initAll(){
if(document.getElementById){
document.getElementById("reload").onclick = anotherCard;
newCard();
}else{
alert("Sorry, your browser doesn't support this script");
}
} function newCard(){
for(var i=0; i<24; i++){
setSquare(i);
}
} function setSquare(thisSquare){
do{
var randomWord = Math.floor(Math.random() * buzzwords.length);
}
while(usedWords[randomWord]);
usedWords[randomWord] = true;
var currSquare = 'square' + thisSquare;
document.getElementById(currSquare).innerHTML = buzzwords[randomWord];
document.getElementById(currSquare).className = "";
document.getElementById(currSquare).onmousedown = toggleColor;
} function anotherCard(){
for(var i=0; i<buzzwords.length; i++){
usedWords[i] = false;
}
newCard();
return false;
} function toggleColor(evt){
if(evt){
var thisSquare = evt.target;
}else{
var thisSquare = window.event.srcElement;
}
if(thisSquare.className == ""){
thisSquare.className = "pickedBG";
}else{
thisSquare.className = "";
}
checkWin();
} function checkWin(){
var winningOption = -1;
var setSquares = 0;
var winners = new Array(31, 992, 15360, 507904, 557328, 1083458, 2162820, 4329736, 8519745, 8659472, 16252928); for(var i=0; i<24; i++){
var currSquare = 'square' + i;
if(document.getElementById(currSquare).className != ''){
document.getElementById(currSquare).className = 'pickedBG';
setSquare = setSquare | Math.pow(2, i);
}
} for(var i=0; i<winners.length; i++){
if((winners[i] & setSquare) == winners[i]){
winningOption = i;
}
} if(winningOption > -1){
for(var i=0; i<24; i++){
if(winners[winningOption] & Math.pow(2, i)){
currSquare = 'square' + i;
document.getElementById(currSquare).className = "winningBG";
}
}
}
}
脚本执行后效果如下:

示例代码下载:
了解 JavaScript (4)– 第一个 Web 应用程序的更多相关文章
- 【转载】ASP.NET MVC Web API 学习笔记---第一个Web API程序
1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过 ...
- ASP.NET MVC3入门教程之第一个WEB应用程序
本文转载自:http://www.youarebug.com/forum.php?mod=viewthread&tid=91&extra=page%3D1 上一节,我们已经搭建好了AS ...
- ASP.NET MVC Web API 学习笔记---第一个Web API程序
http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html GetListAll /api/Contact GetListBySex ...
- ASP.NET MVC Web API 学习笔记---第一个Web API程序【转】
http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html 1. Web API简单说明 近来很多大型的平台都公开了Web API. ...
- ASP.NET MVC Web API 学习笔记---第一个Web API程序---近来很多大型的平台都公开了Web API
1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过 ...
- Windows Azure入门教学系列 (二):部署第一个Web Role程序
本文是Windows Azure入门教学的第二篇文章. 在第一篇教学中,我们已经创建了第一个Web Role程序.在这篇教学中,我们将学习如何把该Web Role程序部署到云端. 注意:您需要购买Wi ...
- 002.Create a web API with ASP.NET Core MVC and Visual Studio for Windows -- 【在windows上用vs与asp.net core mvc 创建一个 web api 程序】
Create a web API with ASP.NET Core MVC and Visual Studio for Windows 在windows上用vs与asp.net core mvc 创 ...
- javascript面向对象创建高级 Web 应用程序
目录 JavaScript 对象是词典 JavaScript 函数是最棒的 构造函数而不是类 原型 静态属性和方法 闭包 模拟私有属性 从类继承 模拟命名空间 应当这样编写 JavaScript ...
- 目前在做的一个web应用程序的前端选型
最近进入了一个新的项目组,要新起一个项目.这个Web项目是一个企业内部使用的系统,主要用来记录.追踪.管理潜在客户的数据.该系统有以下特点: 需要支持IE10及以上版本: 后端采用micro serv ...
- Spring Boot入门教程1、使用Spring Boot构建第一个Web应用程序
一.前言 什么是Spring Boot?Spring Boot就是一个让你使用Spring构建应用时减少配置的一个框架.约定优于配置,一定程度上提高了开发效率.https://zhuanlan.zhi ...
随机推荐
- unreal3对象属性自动从配置文件中加载的机制
unrealscript中有两个与属性自动配置相关的关键字: config/globalconfig 当把它们应用于属性时,对象在创建后,该属性的初始值会被自动设置为相对应ini文件中的值. 举例来说 ...
- 关于 webapi ajax进度条信息设置
1.Web.config 设置跨域 <httpProtocol> <customHeaders> <add name="Access-Control-Allow ...
- 云计算和大数据时代网络技术揭秘(十七)VOQ机制
VOQ机制 本章介绍的VOQ是一种新型的QoS机制,目的是为了解决著名的交换机HoL难题. 但VOQ强烈依赖于调度算法,例如,一个48口的交换机,每个端口都要维护48-1个FIFO缓存队列, 一共48 ...
- 阿里云配置nginx+php+mysql
#yum -y install php mysql mysql-server mysql-devel php-mysql php-cgi php-mbstring php-gd php-fastcgi ...
- 校验两次密码一致的js代码
function checkpasswd(){ var passwd = document.getElementByIdx_x_x_xx_x('passwd').value; var repasswd ...
- Round函数
Round():函数返回一个数值,舍入到指定的长度或精度 eg: --1) ) ---->123.9990 ) ---->124.0000 --3为需要舍入的位数 --2) ) ----- ...
- jquery实现checkbox的全选
<html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"> < ...
- 利用Access-Control-Allow-Origin响应头解决跨域请求
//允许任何域名访问 header("Access-Control-Allow-Origin: *"); //指定域名允许跨域 header("Access-Contro ...
- delphi 十进制十六进制转换
delphi有提供十进制转换成十六进制的函数: IntToStr(); 返回值为String // 十进制转十六进制 var i: integer; str: string; begin i := ...
- java基础知识分析: final , finally,finalize
final final-修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 abstract的,又被声明为final的.将变量或方 ...