一、目标
该笔记的目的是引导读者借助WampServer平台和MySQL数据库,利用HTML/CSS/JS/PHP设计一个能够进行实现数据分页显示、数据选择、数据详细信息查看功能的数据库网页。该数据库网页的效果如图1所示。区域1实现数据分页功能,区域2能够实现用户自主选择数据,区域5实现数据详细信息的查看,区域6为一个按钮(链接)。点击区域6按钮时,能跳转到另一页面,对用户所选择的数据进行进一步分析与可视化。
图1 分页数据库网页效果
该笔记假定读者已经能自己动手利用WampServer搭建出数据库网页,即利用PHP将获取服务器MySQL数据库中的数据,并将其呈递给JS,最后展示给用户。如尚不能搭建一个简易的网页数据库,请参考Case study:数据库网页构建原理和实践。
二、搭建步骤
-
加载JS数据:假定需要搭建的数据库网页由3个文件组成,即"main.php"、“read_data.php"和"show_data.js”。其中"main.php"用于存放HTML元素。"main.php"调用"read_data.php"来向MySQL数据库中读取数据。"main.php"调用"show_data.js"来实现数据表输出。现在假设PHP已经从MySQL数据库中读取数据表,并且JS已将PHP读取的数据转化为一个名为
points
的JS变量(若对上述步骤不熟悉,请参考Case study:数据库网页构建原理和实践)。执行console.log(points)
,结果如图2所示:
图2 需展示的源数据 -
加载数据分页、数据选择和数据详细信息查看功能模块:向"show_data.js"文件中加入以下代码。其中
print_table_kit
存放了分页输出工具箱的基本参数。该变量最为重要。我们可以暂时不关注其他代码的含义。在print_table_kit
的几个参数中,data
为源数据,table_head
表示在网页中向用户呈现的表格的表头中各字段显示的名字。field_option
表示各字段的功能。其中select
为复选框,呈现效果如图1的区域2;auto
为自动分配整数值,呈现效果如图1的区域3;data
表示直接依照field_option
中对应的字段输出MySQL数据库中的数据;href
表示提供一个链接,用户点击链接后能够查看某条数据的具体信息。max_data_option
表示每页最大数据输出量的几种选择,表现为图1区域1中下拉列表框的各个值。init_max_data
表示开始时默认的最大数据输出量;foreign_key
用于指定跳转到其他页面时传递的变量(例如点击了图1中的Info按钮,跳转到另一个页面来查看某一条特定数据的详细信息。但另一个页面必须得知道用户需要查看的是哪条数据的信息。foreign_key
就用来实现这一功能。同理在点击Analysis!按钮时也会用到);href_display
表现为图1中详细信息查看按钮上的文字显示为Info;href_newage
表示点击Info按钮后是新跳出一个页面,还是原页面跳转到新的URL;href_location
表示点击Info后跳转到的页面(该笔记并不详述跳转后页面的实现代码,因此为了简化,也可以把该值直接设置为任意一个网址,比如"https://www.baidu.com/“);select_button_display
表现为图1中区域6的按钮显示文字为"Analysis!”,用于分析用户选择的数据并进行可视化,同时跳转到新的页面;select_button_location
指定了点击Analysis!按钮后跳转到的界面。同样为了简化,可以直接将其设为百度的网址。
/********* 分页输出工具箱 ********/
/********************************/
// 工具箱参数
var print_table_kit = {
"data": points, //源数据
"table_head": ["Select", "No.", "Location", "Longtitude", "Latitude", "User", "Time", "Detailed"],
//网页中向用户展示的数据表字段名,不影响JS和PHP代码运行
"field_option": ["select", "auto", "data", "data", "data", "data", "data", "href"],
//数据字段种类
// select: 复选框
// auto: 自动分配递增整数值
// data: 显示数据表中对应内容
// href: 提供数据查看链接
"field_data": ["NA", "NA", "location", "long", "lat", "user", "time", "NA"],
//MySQL数据库中对应的数据字段
"max_data_option": [5, 10, 20, 50, 100], //每页最大数据输出量的若干选项
"init_max_data": 20, //默认的每页最大数据输出量
"foreign_key": "picture", //外键,用于查看数据详细信息,或进行进一步数据可视化
"href_display": "Info", //网页中向用户展示的链接的名字,不影响JS和PHP代码运行
"href_newpage": false, //点击链接后是否打开新的网页
"href_location": "./info.php", //点击链接后转到的页面
"select_button_display": "Analysis!", //选中数据后能点击按钮跳转到另一网页,该按钮在网页中展示的文字
"select_button_location": "analysis_result.php"
//点击按钮后跳转到的页面
}
//辅助变量和函数
var seldat=[]; //用户点击checkbox后所有选中的数据
function min(a,b){ //获取最小值
if(a>b) {return b;}
return a;
}
Array.prototype.remove = function(val) { // Array的remove方法arr.remove()
var index = this.indexOf(val); // 删除数组中为某一值的元素
if (index > -1) {
this.splice(index, 1);
}
};
function contains(arr, obj) { //判断obj是否在arr内
var i = arr.length;
while (i--) {
if (arr[i] === obj) {
return true;
}
}
return false;
}
var setCookie = function (name, value, day) { //设置cookie变量
//当设置的时间等于0时,不设置expires属性,cookie在浏览器关闭后删除
var expires = day * 24 * 60 * 60 * 1000;
var exp = new Date();
exp.setTime(exp.getTime() + expires);
document.cookie = name + "=" + value + ";expires=" + exp.toUTCString();
};
// Select模块功能:点击全选按钮,选中所有数据
function selall(){
var items_all = document.getElementsByName("select_all");
var items = document.getElementsByName("selitem");
if(items_all[0].checked){
for (i = 0; i < items.length; i++){
items[i].checked = true;
if(!contains(seldat, items[i].value)){
seldat.push(items[i].value);
}
}
} else{
for (i = 0; i < items.length; i++){
items[i].checked = false;
seldat.remove(items[i].value);
}
}
//console.log(seldat);
}
// Select模块功能:点击数据复选框,选中或取消选中数据
function click_databox(box){
var items_all = document.getElementsByName("select_all");
if(box.checked){
if(!contains(seldat, box.value)){
seldat.push(box.value);
}
//刷新全选复选框
var items = document.getElementsByName("selitem");
var items_all_set = true;
for (var i = 0; i < items.length; i++){
if(!items[i].checked) { items_all_set = false; }
}
items_all[0].checked = items_all_set;
} else{
seldat.remove(box.value);
//刷新全选复选框
items_all[0].checked = false;
}
//console.log(seldat);
}
// Select模块功能:刷新页面中的复选框
function renovate_checkbox(){
var items_all_set = true;
// 刷新单项数据复选框
var items = document.getElementsByName("selitem");
for (i = 0; i < items.length; i++){
if(contains(seldat, items[i].value)){
items[i].checked = true;
} else {
items_all_set = false;
}
}
// 刷新全选复选框
var items_all = document.getElementsByName("select_all");
items_all[0].checked = items_all_set;
}
// Select模块功能:点击Analysis按钮,js数组传到Cookie,跳转到数据分析与可视化界面
function analysis(){
setCookie('arr',seldat,1); //利用COOKIE将选择的数据的外键名传给新的页面
location.href = print_table_kit["select_button_location"];
//console.log(arr);
//alert("选择的个数为:" + arr.length);
}
// href模块功能:点击Info按钮,跳转到图片info界面
function info(path, new_page){
setCookie("query_key",path,1); //利用COOKIE向新页面传送外键信息
if(new_page){
window.open(print_table_kit["href_location"]);
} else{
location.href = print_table_kit["href_location"];
}
}
// data模块功能:负责展示第i条数据
function showdata(i){
var cout = "<tr>";
var FK_value = print_table_kit["data"][i][print_table_kit["foreign_key"]];
for(var j=0; j<print_table_kit["table_head"].length; j++){
cout += "<td>";
if(print_table_kit["field_option"][j] == "select"){
cout += '<label>';
cout += '<input name="selitem" type="checkbox" οnclick="click_databox(this)" value="' +
FK_value + '" />';
cout += '</label>';
} else if(print_table_kit["field_option"][j] == "auto"){
cout += String(i+1);
} else if(print_table_kit["field_option"][j] == "data"){
cout += print_table_kit["data"][i][print_table_kit["field_data"][j]];
} else if(print_table_kit["field_option"][j] == "href"){
cout += '<button type="button" οnclick=\'info("' +
FK_value + '", ' + print_table_kit["href_newpage"] + ')\'>' +
print_table_kit["href_display"];
}
cout += "</td>";
}
cout += "</tr>";
return cout;
}
//分页控件:翻到下一页
function nextpage(page, max_page){
var objS = document.getElementById("changesize");
var max_data = objS.options[objS.selectedIndex].value;
if(page < max_page){
print_data(max_data, page+1);
}
}
//分页控件:翻到上一页
function formerpage(page){
var objS = document.getElementById("changesize");
var max_data = objS.options[objS.selectedIndex].value;
if(page > 1){
print_data(max_data, page-1);
}
}
//分页控件:翻到首页
function firstpage(){
var objS = document.getElementById("changesize");
var max_data = objS.options[objS.selectedIndex].value;
print_data(max_data, 1);
}
//分页控件:翻到尾页
function lastpage(max_page){
var objS = document.getElementById("changesize");
var max_data = objS.options[objS.selectedIndex].value;
print_data(max_data, max_page);
}
//输出分页按钮
function print_switchpage(max_data, page){
var max_page = Math.ceil(print_table_kit["data"].length/max_data);
var cout = '<a href="###" οnclick=firstpage()>\<\<</a>';
cout += ' ';
cout += '<a href="###" οnclick="formerpage('+String(page)+')">\<</a>';
cout += ' ';
cout += '<a href="###">'+ String(page) +'</a>';
cout += '/' + String(max_page);
cout += ' ';
cout += '<a href="###" οnclick="nextpage('+String(page)+','+String(max_page)+')">\></a>';
cout += ' ';
cout += '<a href="###" οnclick="lastpage('+String(max_page)+')">\>\></a>';
cout += ' ';
return cout;
}
//改变最大数据输出量下拉列表框的值触发事件
function change_maxdata(){
var objS = document.getElementById("changesize");
var max_data = objS.options[objS.selectedIndex].value;
print_data(max_data, 1);
}
//输出改变最大数据输出量的下拉列表框
function print_changesize(max_data){
var cout = 'Maximum output: ';
cout += '<select id="changesize" οnchange="change_maxdata();">';
for(var i=0; i<print_table_kit["max_data_option"].length; i++){
cout += '<option value="'+String(print_table_kit["max_data_option"][i])+'"';
if(print_table_kit["max_data_option"][i] == max_data){
cout += ' selected';
}
cout += '>';
cout += String(print_table_kit["max_data_option"][i]);
cout += '</option>';
}
cout += '</select>';
return cout;
}
// 输出表头
function print_tablehead(){
var cout = "<table>";
cout += "<tr class='head'>";
for(var i=0; i<print_table_kit["table_head"].length; i++){
cout += "<th>";
cout += print_table_kit["table_head"][i];
if(print_table_kit["field_option"][i] == "select"){
cout += '<label>';
cout += '<input name="select_all" type="checkbox" οnclick="selall()" value="" />';
cout += '</label>';
}
cout += "</th>";
}
return cout;
}
// 输出表格
function print_data(max_data, page){
num_data = 0; //页面中显示数据个数初始化
// 输出分页按钮
var cout = print_switchpage(max_data, page);
// 输出最大数据输出量下拉列表框
cout += print_changesize(max_data);
// 输出表头
cout += print_tablehead();
// 输出数据
var start = (page - 1) * max_data;
for (var k = start; k < start + Number(min(max_data, print_table_kit["data"].length - start)); k += 1){
cout += showdata(k);
}
cout += "</table>";
// 输出数据分析按钮
cout += '<a href="###" οnclick="analysis()">'+print_table_kit["select_button_display"]+'</a></p>';
document.getElementById("showtb").innerHTML = cout;
//刷新所有select复选框
renovate_checkbox();
}
/******** /分页输出工具箱 ********/
/********************************/
- 在"main.php"中加入代码
<div id="showtb"></div>
。这段id为"showtb
"的区域将会被填充为数据表。同时要为<body>
添加onload
事件,即<body onload="init()">
。其中init()
函数必须要执行的内容如下。此时就可以实现数据分页、数据选择以及数据详细信息查看功能(伪链接)。
function init(){
print_data(print_table_kit["init_max_data"], 1);
}