前端开发一些总结

话说自己差不多有10年没有写JavaScript和 CSS了,还记得2002年春天连续一个多月的晚间不停的写HTML/CSS/JavaScript/ASP 才把 AndyFans.Com  和 大学班级网站弄上线。由于工作原因,之后再也没有这么大规模写过HTML/CSS/JS这些程序。

但一直没有停止对JavaScript/CSS 的关注,最近整理文章的时候看到自己在03年写过的几个JS类库,当时感觉很牛,现在看来很垃圾了。脚本大量依赖于M$.IE浏览器,现在虽然IE浏览器是主流,但不规范的地方太多,存在大量兼容问题。

最近看了一下JQuery类库,有了这个函数库,前端做什么特效都变得简单极了。

介绍几个实用的功能:

1  将HTML表格数据导出Excel下载;

假如页面上有一张表格,需要把这个表格的数据导出成Excel,如果只考虑IE浏览器,那就很简单了。用VBScript创建一个Excel对象,然后将表格数据导入就可以了。但考虑到FF,Chrome用户那就要服务器端来输出。

首先要将表格数据解析出来才可以。如果没有 JQuery可以通过节点关系来实现。 但有了 JQuery这个就简单多了。

/**
 * 将id 为 tableId的表格转换成二维数组
 * @param tableId
 * @returns {Array}
 */
function table2Array(tableId){
	var tab = $("#"+tableId);
	var rows=[];
	tab.find("tr").each(
			function(i,e){
					var columns=[];
					$(e).find("td").each(
							function (j,td){
								columns[j]=$(td).text();
							}
					);
					rows[i]=columns;
			}
	);
	return rows;
}

上面的方法实现了对Table的解析,实际中向后台发送的数据可能是某种格式的文本。为了方便再定义个数组拼接成字符串的函数。

/**
 * 将数组中的元素用固定的分割符号链接成字符串
 * @param arr
 * @param flag
 * @returns {String}
 */
function join(arr,flag){
	var string="";
	for(var i=0;i<arr.length;i++){
		string+=arr[i];
		if(i!=arr.length-1){
			string+=flag;
		}
	}
	return string;
}
 
function _GE_(id){
    return document.getElementById(id);
}
function _OV_(id,value){
    _GE_(id).innerHTML=value;
}

有了这些就可以发送数据了。因为服务器端返回的是二进制数据所以不易用Ajax提交,采用隐藏一个iframe方式提交。

/**
 * 
 * 导出表格数据到Excel
 * @param tableId
 */
function exportTable2Excel(tableId){
	var rows = table2Array(tableId);
	var data="";
	for(var i=0;i<rows.length;i++){
		data+=join(rows[i],"\t");
		data+="\n";
	}
 
    postFormDownload({"dataName":data},"URL");
}
 
/**
 * 隐藏表单向服务器端提交数据。
 * 服务器端返回的是二进制数据流,自动下载
 * @param data {name:value,name:value}
 * @param url 接收数据地址
 */
function  postFormDownload(data,url){
	showProcess();
    var iframeId="__exel_iframe__";
    var divId="__exel_div__";
    var formId="__exel_form__";
    var elements = "<iframe id='"+iframeId+"' name='"+iframeId+"' style='display:none'></iframe><form  id='"+formId+"' action='"+url+"' method='post' target='"+iframeId+"' style='display:none'>";
    for(var key in data){
    	if(data[key].length>200){
    		elements+="<textarea id='"+key+"' name='"+key+"'>"+data[key]+"</textarea>"; 
    	}else{
    		elements+="<input type='hidden' id='"+key+"' name='"+key+"' value='"+data[key]+"'/>"; 
    	}
 
    }
    elements+="</form>";
    if(_GE_(divId)){
       document.body.removeChild(_GE_(divId)); 
    }
    var div = document.createElement("div");
        div.style.display="none";
        div.setAttribute("id",divId);
        div.innerHTML=elements;
        document.body.appendChild(div);
        _GE_(formId).submit(); 
       //该iframe返回的mineType不是 text/html 或 text/plain格式,所以无法通过onreadyStateChange或onload等事件捕获状态。
 
}

导出函数会判断当前页面是否存在隐藏iframe和form,如果不存在就创建。表单向iframe提交数据。

  function exportData(){
     exportTable2Excel('表ID');
   }

到此实现了表格到Excel的导出。服务器端接收到数据后按照分隔符分开,调用相关的API生成Excel数据流,通过浏览器下载到客户电脑上。
服务器端返回的Header中增加以下字段才能提示下载,否则数据将会在iframe中被显示,而iframe是不可见的。

Content-Type: application/vnd.ms-excel;charset=utf-8
Content-Disposition : attachment;filename=export.xls

说起隐藏iframe,在03年的时,几乎没有Ajax的概念,当时的大部分特效都用iframe实现,比如聊天室刷新,提交表单也是其中的主要功能了。
在iframe中可以通过parent.window.function()来调用父窗口的函数。也就是当iframe中的程序处理完之后会通过窗口来调用父窗口的函数,形成了一种回调机制。
比如:上传附件功能。现在有很多上传附件功能是通过Flash实现的,也有个别的通过Activex实现的更强功能。
像Gmail中那种’添加附件‘ 功能,通过动态添加<input元素来实现的,将表单提交向一个隐藏的iframe,iframe中不断回调上传进度。

值得注意的一点是:<input type=”file” 这个元素从安全角度考虑,不允许给它赋值。但是可以读取和监听。

当点 ‘添加附件’时候调用一个Javascript函数,动态添加一个file元素,同时调用该元素的click方法就可以打开文件对话框了。

 function addAtt(){
    var form = document.getElementById("upform");
    var input = document.createElement("input");
        input.setAttribute("type","file");
        input.style.display="none";
        input.onchange=uploadChange(input);
        form.appendChild(input);
       //以上代码或者修改成在某个DIV下直接插入:<input type="file" name="filename" id="filename"  style="display:none" onchange="uploadChange(this)"/>
	if(document.all){ 
		input.click(); 
	}else{
		var a=document.createEvent("MouseEvents");
		a.initEvent("click", true, true);  
		input.dispatchEvent(a); 
	} 
}
function uploadChange(obj){
     //TODO 检查文件格式等操作
    var form = document.getElementById("upform");
        form.submit();
}
function uploadCompleted(data){
  //TODO process more
}

服务器端表单处理成功后将调用父窗口的uploadCompleted(data)函数;

貌似 jquery 也有插件能够实现带进度条的上传功能。目前还没有测试。

先写这些吧。前端是一个很细致的工作,要有耐心。更要从用户的角度考虑,怎么做才能够做出一个实用,易用,好用的产品。

分享到: 更多