HTML+CSS+JavaScript实现仿猫眼电影购票选座

一、功能实现

(1)在页面左侧区域,单击“可选座位”,将座位设置为“已选座位”,一次最多选5

个座位。右侧座位号汇总区域显示已选中的座位号,并显示电影票总价。

(2)在页面左侧区域,单击“已选座位”,将座位设置为“可选座位”。右侧选座信息汇总区域取消相应的座位号,并显示电影票总价。

(3)单击页面右侧选座信息汇总区域座位号右上角的“×”,将座位设置为“可选座位”。选座信息汇总区域取消相应的座位号,并显示电影票总价。

(4)“已选座位”数量不为0时,“确认选座”按钮设置为可用状态,选座信息汇总区域显示。“已选座位”数量为0时,“确认选座”按钮设置为不可用状态,选座信息汇总区域隐藏。

案例在Chrome浏览器运行效果,如图9-1所示。

 二、HTML布局

1.页面左侧选座区域布局

由图9-1可知,左侧选座区域是8排10列,以第7排为例,介绍左侧选座区域布局,示例代码如下。CSS代码详见本书源码。

<div class="seats-wrapper">
   <div class="row">
      <span class="seat selectable" data-column-id="9" data-row-id="7" </span>
      <span class="seat selected" data-column-id="8" data-row-id="7" </span>
      <span class="seat selected" data-column-id="7" data-row-id="7" </span>
      <span class="seat selectable" data-column-id="6" data-row-id="7" </span>
      <span class="seat selectable" data-column-id="5" data-row-id="7" </span>
      <span class="seat selectable" data-column-id="4" data-row-id="7" </span>
      <span class="seat selectable" data-column-id="3" data-row-id="7" </span>
      <span class="seat empty" data-column-id="" data-row-id="7" data-st="E" </span>
      <span class="seat sold" data-column-id="2" data-row-id="7" data-st="LK" </span>
      <span class="seat sold" data-column-id="1" data-row-id="7" data-st="LK" </span>   
</div>
</div>

上述代码中,“<div class="seats-wrapper">”是选座区域的容器,1个“<div class="row">”元素代表一排,1个span元素代表1个座位。座位的class属性值中,“seat”代表公共样式、“selectable”代表可选座位、“selected”代表已选座位、“empty”代表不显示座位、“sold”代表座位已经售出;座位的“data-column-id”属性代表座位号;“data-row-id”属性代表座位在第几排;“data-st”属性代表座位状态,若是值等于“E”代表座位不显示,若是值等于“LK”代表座位被锁定。

2.页面右侧选座信息汇总区域和票价区域布局

由图9-1可知,右侧选座信息汇总区域已选两个座位,分别是“7排8座”和“7排7座”,总价60,“确认选座”按钮处于可用状态。HTML示例代码如下,CSS代码详见本书源码。

1  <div class="ticket-info">
2          <div class="no-ticket" style="display:none">
3             <p class="buy-limit">座位:一次最多选5个座位</p>
4             <p class="no-selected">请<span>点击左侧</span>座位图选择座位</p>
5          </div>
6          <div class="has-ticket" style="display:block">
7             <span class="text">座位:</span>
8             <div class="ticket-container" data-limit="5">
9   <span data-row-id="7" data-column-id="8" data-index="7-8" class="ticket">7排8座</span> 
10  <span data-row-id="7" data-column-id="7" data-index="7-7" class="ticket">7排7座</span>
11          </div>
12          <div class="total-price">
13            <span>总价 :</span>
14            <span class="price">60</span>
15          </div>
16 </div>

上述代码中,第1行代码“<div class="ticket-info">”是本区域的容器;第2行代码“<div class="no-ticket" style="display:none">”是没有选中座位的容器,“已选座位”数量不为0时,它的状态是隐藏;第6行代码“<div class=" has-ticket" style="display:block">”是有选中座位的容器,“已选座位”数量不为0时,它的状态是显示;第8行代码“<div class="ticket-container" data-limit="5">”是座位号信息的容器;第9-10行代码中的1个span元素代表一个座位号信息,它的class属性值是“ticket”;第12行代码“<div class="total-price">”是电影票总价的容器;第14行代码“<span class="price">60</span>”显示电影票总价。

三、工具函数

由功能描述(1)、(2)、(3)可知,选中或取消选中座位时都需要重新计算电影票总价,因此将计算电影票总价功能封装成函数showTotalbill(),以便在选中或取消选中座位时调用。示例代码如下。

var total_bill = 0 ;//总价
var pricePerTicked = 30;//单价
function showTotalbill(){
total_bill = document.querySelectorAll(".ticket").length * pricePerTicked;
document.querySelector('.price').innerHTML = total_bill;
}

上述代码声明了函数showTotalbill(),它的功能是计算电影票总价并显示在相应的位置。其中,变量total_bill代表电影票总价;变量pricePerTicked代表电影票单价;电影票总价的值是电影票单价乘以电影票数量。

由功能描述(4)可知,“已选座位”数量不为0时,“确认选座”按钮设置为可用状态,选座信息汇总区域显示。“已选座位”数量为0时,“确认选座”按钮设置为不可用状态,选座信息汇总区域隐藏。每次选中或取消座位时,都将执行上述过程,因此将此功能封装成函数setTicketsinfoState ()。示例代码如下。

1 function setTicketsinfoState (){
2   if(document.querySelectorAll(".ticket").length>0){
3	     document.querySelector('.confirm-btn').classList.remove('disable');
4	     document.querySelector('.no-ticket').style.display = 'none';
5	     document.querySelector('.has-ticket').style.display = 'block';
6   }
7  else{
8	     document.querySelector('.confirm-btn').classList.add('disable');
9	     document.querySelector('.no-ticket').style.display = 'block';			
10	     document.querySelector('.has-ticket').style.display = 'none';
11  }
12 }

上述代码中,第1行代码声明了函数setTicketsinfoState();第2-11行代码判断选中座位的集合长度,如果大于0,将“确认选座”按钮设置为可用状态,选座信息汇总区域显示;否则,执行相反的操作。

四、选座

在页面左侧区域,单击“可选座位”,将座位设置为“已选座位”,单击“已选座位”,将座位设置为“可选座位”,一次最多选5个座位,同时右侧座位汇总区域显示或取消已选中的座位号,并显示电影票总价。选座程序流程图如图9-2所示。

由于左侧选座区域是8排10列,如果为每一个座位绑定单击事件,比较消耗资源,因此可以通过事件委托为座位的父元素“<div class="seats-wrapper">”绑定单击事件。示例代码如下。

1 document.querySelector('.seats-wrapper').onclick = function (e) {
2 if (e.target.nodeName!="SPAN"||e.target.getAttribute('data-st') == 'E' || e.target.getAttribute('data-st') == 'LK')  {
3	return;
4 }
5 else if (e.target.classList.contains('selected')) { 
6	e.target.classList.remove('selected');
7	e.target.classList.add('selectable');
8	var tickets = document.querySelectorAll(".ticket");
9	var selectd = e.target.getAttribute('data-row-id') + '-' + e.target.getAttribute('data-column-id');
10	for (var i = 0; i < tickets.length; i++) {
11		if (tickets[i].getAttribute('data-index') == selectd) {
12			document.querySelector(".ticket-container").removeChild(tickets[i]);
13			break;
14		}
15	}	
16	showTotalbill();
17 } else if (document.querySelectorAll(".ticket").length >= 5) {
18	alert('一次最多买5张');
19    }
20 else{
21	e.target.classList.remove('selectable');
22	e.target.classList.add('selected');		
23	var newUL = document.querySelector(".ticket-container");
24	var s = document.createElement('span');
25	s.setAttribute('data-row-id', e.target.getAttribute('data-row-id'));
26	s.setAttribute('data-column-id', e.target.getAttribute('data-column-id'));
27 s.setAttribute('data-index',e.target.getAttribute('data-row-id')+'-'+e.target.getAttribute('data-column-id'));
28	s.className = 'ticket';
29	s.innerText = e.target.getAttribute('data-row-id') + '排' + e.target.getAttribute('data-column-id') + '座';
30	newUL.appendChild(s);
31	showTotalbill();
32   }
33 setTicketsinfoState();
34 }

 上述代码中,第1行代码利用事件委托,为所有座位的父元素绑定单击事件及其处理程序;第2行代码判断如果单击的不是座位,或者单击的座位已锁定或empty,则程序返回;第5-16行代码判断如果单击的座位已经处于选中状态,则取消它的选中状态,删除右侧对应座位号,并计算和显示电影票总价;第17-19行代码判断如果单击的座位处于未选中状态且已选中座位大于5个,则弹出提示框提示;第21-32行代码实现将选中的座位设置为选中状态,在右侧选座信息汇总区域添加座位信息,并计算和显示电影票总价;第33行代码调用封装的函数setTicketsinfoState()设置右侧选座信息汇总区域状态。

五、取消选座

单击页面右侧选座信息汇总区域座位号右上角的“×”,将座位设置为“可选座位”,同时选座信息汇总区域取消相应的座位号,并显示电影票总价。由于座位号可能有5个,如果为每1个座位号绑定单击事件,比较消耗资源,因此可以通过事件委托给座位号的父元素“<div class="ticket-container"></div>”绑定单击事件及其处理程序。示例代码如下。

1 document.querySelector('.ticket-container').onclick = function (e) {
2   if (document.querySelectorAll(".ticket").length <= 0) {
3	  return;
4   }
5   var selected = document.querySelectorAll(".selected");
6   var ticket = e.target.getAttribute('data-index');
7   for (var i = 0; i < selected.length; i++) {
8     if (selected[i].getAttribute('data-row-id') + '-' + selected[i].getAttribute('data-column-id') == ticket) 
9     {
10	     selected[i].classList.remove('selected');
11	     selected[i].classList.add('selectable');
12	     break;
13	 }
14  }
15  e.target.parentNode.removeChild(e.target);
16  showTotalbill();
17  setTicketsinfoState();
18 }

上述代码中,第1行代码利用事件委托,为所有座位号的父元素绑定单击事件及其处理程序;第2行代码判断如果座位号的集合长度小于0,则程序返回;第5-15行代码将删除的座位号对应的座位设置成可选的状态;第16-17行代码设置右侧选座信息汇总区域显示或隐藏,并计算和显示电影票总价。

视频讲解地址:HTML+CSS+JavaScript实现仿猫眼电影购票_哔哩哔哩_bilibili

源码:清华大学出版社-图书详情-《JavaScript前端开发与实例教程(微课视频版)》

猜你喜欢

转载自blog.csdn.net/weixin_43396749/article/details/128010851