编码原则
Js控件代码3部曲
(1)设置元素的 状态 在onready中添加
(2)设置元素的 动作, 每个动作 封装成 function(enclosure)
(3)remove load之前 删除方法,属性
DeferList1次和 3次DeferList 14s vs 29s
1次:
var tempAr=[];
var queryTask=new esri.tasks.QueryTask(getQueryUrl(0));//station
var query=new esri.tasks.Query();
query.outSpatialReference=mapAppObj.map.spatialReference;
query.outFields=["*"];
query.returnGeometry=true;
query.where="isFinished=1";
tempAr.push(queryTask.execute(query));
queryTask=new esri.tasks.QueryTask(getQueryUrl(1));//line
tempAr.push(queryTask.execute(query));
queryTask=new esri.tasks.QueryTask(getQueryUrl(2));//sections
tempAr.push(queryTask.execute(query));
var deferList=new dojo.DeferredList(tempAr);
deferList.then(function(results){
时间:
4次:
initStationFeatures()
initSectionFeatures()
initLineFeatures()
时间:
引用类型, 指向变量控制在1
举例:
var arr=[obj,obj2,obj3,obj4]
var newArr=[];
for(var i=0;i<=arr.length-1;i++){
if(…){
newArr.push(arr[i])
}
}
Return newArr
Obj: arr[0],newArr[0],指向。
这样性能低于 arr[0]
引用类型 军规 让指向变量只有一个,
Case1:
newFeatures 和features都指向 features
var newFeatures=[];//仅入 京之区
for(var i=0;i<=features.length-1;i++){
var oneFeature=features[i];
var name=oneFeature.attributes.NAME;
时间:523ms
case2:
只有features
for(var i=0;i<=features.length-1;i++){
var oneFeature=features[i];
var name=oneFeature.attributes.NAME;
//Yellow
if(name=="昌平区"||name=="丰台区"){
oneFeature.setSymbol(new
oneFeature.setInfoTemplate(null);
targetLayer.add(oneFeature);
}
时间:219ms
2M到4M 和 2s到4s
若不会耗尽客户端的内存。用空间换时间。
动态的部分越少越好
Iframe越少越好
原因:iframe导致内存泄露.
click军规-禁止在代码中触发事件
事件金留给用户处理
函数三部曲
--1检查异常值
--2执行运算
--3返回结果
页面两部曲
--1.编写HTML
--2. documentReady中请求数据
--3.documentReady中绑定事件
代码检查F12
探查器->开始采样->调用树
说明:计数,执行次数
包含时间,每次执行的毫秒数
代码不好改,是因为不自然
不要在HTML中onclick
原因:1不好维护
2 副作用很多
300*300 table显示 性能要义:
(1) 不要在td中加div
(2) 一次把300*300的html写好后,再添加到dom元素中。(只用一次append()或html())
(3) 尽量不要给td设置id,id个数90000时,对性能影响很大.
多进程控制
多个异步进程,如何同步
//总结:第一个异步请求发出前blockUI。 Sentinal++; 每个接收函数中将
Sentinal--,并判断sentinal是否是0;如果是,解除block。执行后续操作。
var hangCount=0;
function blockMap(){
$.blockUI({
message
: '<h1><img
src="../img/common/busy.gif"></img> 地图加载中…</h1>'
});
};
function unBlockMap(){
$.unblockUI();
}
//递减sentinal,如果接收数据完毕,则解除block
function
minusCheckHangZero(){
if(hangCount==0){
unBlockMap();
return;
}
hangCount--;
if(hangCount==0){
unBlockMap();
return;
}
};
$(document).ready(function(){
console.log("map.html
ready() is triggered");
mapAppObj=new
mapObject();
mapAppObj.initBaseMap();
blockMap();
//进程1
hangCount++;
mapAppObj.featuresDictionary.getLinesInOd();//获取OD中所有line
//进程2
hangCount++;
mapAppObj.featuresDictionary.getStationsInOd();//获取OD中所有Station
//进程3
hangCount++;
mapAppObj.featuresDictionary.getAllFeatures(function(){
mapAppObj.lineLayer.init();//依赖进程3
mapAppObj.stationLayer.init(false);//依赖进程3
minusCheckHangZero();
});//callback
end
//进程4
mapAppObj.labelLayer.addToMap();
});
数据加载前,必须BlockUI
setInterval和setTimeout
闪烁效果
$(function(){
var
bIn=setInterval(function(){
if($("#dv").hasClass("dNone")){
$("#dv").removeClass("dNone");
}
else{
$("#dv").addClass("dNone");
}
},300);
setTimeout(function(){
clearInterval(bIn);
},2000);
});
Confirm Alert Prompt
(1)var flag=confirm(“确定离开此页面”);
(2)alert(“未能获取数据”);
(3)
var str=prompt(“请输入工程师姓名”,”姓名”);
Window_Anchor对象
新建选项卡
<a class="div1ADetail"
href="'+onePoi.detailUrl+'" target="_blank">详情>></a>
备注:去掉下划线 text-decoration:none
伪造新建选项卡
var $a=$('<a
href="http://www.baidu.com" target="_blank"></a>');
$a.appendTo("body");
$a[0].click();
$a.remove();
Location对象_路径符号
获取网站根目录
//获取根目录名 /odGIS
function getRootName(){
var path
= document.location.pathname.substr(1);
path
= "/" + path.substr(0, path.indexOf("/"));
return path;
}
/到端口号;./当前页的父目录;../当前目录向上
Cookie对象
遍历cookies
客户端:所有cookies存储在document.cookie中。
格式:co1=val1;col2=val2;col3=val3;
摘要:
取所有cookies |
document.cookie |
function
loopCookies(){
var
cosStr=document.cookie;
if(cosStr==""){
console.log("no
cookie exist");
return;
}
var
cos=document.cookie.split(";");
for(var i=0;i<=cos.length-1;i++){
var
cN=cos[i].split("=")[0];
var
cV=cos[i].split("=")[1];
console.log("Name:"+cN+",Value:"+cV+"\n");
}
}
在baidu上执行效果:
Name:BAIDUID,Value:557D96D13E7C9662F7DCFD9E8C13FED1:FG
Name:
BDRCVFR[DfWFxj3YnYn],Value:mk3SLVN4HKm
Name:
CNZZDATA30080359,Value:cnzz_eid%3D2026158897-1392476638-http%253A%252F%252Fwww.baidu.com%252F%26ntime%3D1392859028%26cnzz_a%3D9%26sin%3Dnone%26ltime%3D1392852635349%26rtime%3D6
Name:
BDRCVFR[feWj1Vr5u3D],Value:I67x6TjHwwYf0
Name:
BD_CK_SAM,Value:1
Name:
H_PS_PSSID,Value:5095_1447_5213_4264_4760_5244_5188
创建cookie
//源自w3school
http://www.w3school.com.cn/js/js_cookies.asp
创建cookie
function setCookie(c_name,value,expiredays)
{
var exdate=new Date()
exdate.setDate(exdate.getDate()+expiredays)
document.cookie=c_name+ "=" +escape(value)+
((expiredays==null) ? "" : ";expires="+exdate.toGMTString())
}
获取cookie
function getCookie(c_name)
{
if (document.cookie.length>0)
{
c_start=document.cookie.indexOf(c_name + "=")
if (c_start!=-1)
{
c_start=c_start + c_name.length+1
c_end=document.cookie.indexOf(";",c_start)
if (c_end==-1) c_end=document.cookie.length
return unescape(document.cookie.substring(c_start,c_end))
}
}
return ""
}
String 对象
字符串包含
- var Cts = "bblText";
- if(Cts.indexOf("Text") >= 0 )
- {
- alert('Cts中包含Text字符串');
- }
JSON和字符串互相转换
Json转
字符串:var last= JSON.stringify(obj)
字符串转Json: JSON.parse(string)
String Object Methods
Method |
Description |
Returns the character at the specified index |
|
Returns the Unicode |
|
Joins two or more strings, and returns a copy of the joined |
|
Converts Unicode |
|
Returns the position of the first found occurrence of a |
|
Returns the position of the last found occurrence of a |
|
Compares two strings in the current locale |
|
Searches for a match between a regular expression and a |
|
Searches for a match between a substring (or regular |
|
Searches for a match between a regular expression and a |
|
Extracts a part of a string and returns a new string |
|
Splits a string into an array of substrings |
|
Extracts the characters from a string, beginning at a |
|
Extracts the characters from a string, between two specified |
|
Converts a string to lowercase letters, according to the |
|
Converts a string to uppercase letters, according to the |
|
Converts a string to lowercase letters |
|
Returns the value of a String object |
|
Converts a string to uppercase letters |
|
Removes whitespace from both ends of a string |
|
Returns the primitive value of a String object |
Form对象
属性名 |
取值 |
说明 |
action |
action=”test.jsp” |
提交哪个jsp或servlet |
method |
post get |
提交方式。 get缺点: (1)长度不可超过5k (2)以url形式出现在地址栏,不安全 |
enctype |
multipart/form-data |
以二进制形式提交。用于上传文件 |
Frame对象
Frame调用页面内,和页面内调用frame外
Frame调用内
document.getElementById("frameId").contentWindow.setQueryLayer("line,
section, station");
页面内调用外
window.parent.receivefromGis(arrSendSubway);
Frame去除边框
"<iframe frame-border='0'
></iframe>"
Object对象
遍历对象的属性名
遍历属性名
var
testObject={"Soul":"Shimada","Soul2":"Cozuka"};
for(var temp in testObject){
alert(temp);
}
//result: Soul, Soul2
Input对象
文本框自动补全
//搜索工具,
input-button-tips
function searchTool(){
var
input=null;//关键字
var
button=null;//搜索
var tips=null;//下拉选项
var
_this=this;
//初始化
this.init=function(inputDiv,butnDiv,tipsDiv){
console.log("searchTool.init
is called");
if(inputDiv==null||inputDiv.tagName.toLowerCase()!="input"){
console.log("invalid
para,function searchToo.init()");
return;
}
if(butnDiv==null||butnDiv.tagName.toLowerCase()!="input"){
console.log("invalid
para,function searchToo.init()");
return;
}
if(butnDiv==null||tipsDiv.tagName.toLowerCase()!="div"){
console.log("invalid
para,function searchToo.init()");
return;
}
input=inputDiv;
button=butnDiv;
tips=tipsDiv;
console.log("searchTool
widgets validated");
//文本框获取焦点,显示tips
$(input).on("focus",function(){
console.log("input
focus is triggered");
_this.showTips(true);
});
//文本框失去焦点
$(input).on("blur",function(e){
//onblur,e
always be input itsself
//when
tips.children.click caused inputBlur,
//if
not delay, showTips(false) precede children().click,
//then
unable to selected tip;
console.log("input
blur triggered,hideTips delayed 200ms");
setTimeout(function(){
_this.showTips(false);
},200);
});
//关键字变更
$(input).on("keyup",function(){
console.log("input
keyup is triggered");
_this.updateTips($(this).val());
_this.showTips(true);
});
$(button).on("click",function(){
console.log("search
click is triggered");
var
key=_this.getKey();
console.log("关键字是:"+key);
_this.showTips(false);
});
//点击tips以外的区域,tips关闭
};//end
初始化
//获取输入的关键字
this.getKey=function(){
return
$.trim($(input).val());
};
//显隐备选项
this.showTips=function(flag){
console.log("showTips("+flag+")
is called");
if(flag){
//显示
if($(tips).hasClass("dNone")){
if($(tips).children().length==0){
console.log("no
children in tips,tips won't be showed");
return;
}
var
left=$(input).css("left");
var
top=$(input).css("top")+$(input).css("height");
console.log("tips
location:"+left+","+top);
$(tips).removeClass("dNone");
}
else{return;}
}
else{$(tips).addClass("dNone");}
};
//清空提示项,解除点击事件
this.clearTips=function(){
console.log("clearTips
is called");
var length=$(tips).children().length;
console.log("tips.childeren.length
is:"+length);
$(tips).children().off("click");
$(tips).empty();
};
//更新tips
this.updateTips=function(key){
console.log("updateTips
is called");
this.clearTips();
var
stationTips=mapAppObj.stationIDNameObj.getSimilarStationNames(key);
console.log("tips
get,"+$.toJSON(stationTips));
var
tipsHtml="";
for(var
i=0;i<=stationTips.length-1;i++){
tipsHtml+="<p
class='similarItem'>"+stationTips[i]+"</p>";
}
$(tips).html(tipsHtml);
$(".similarItem").on("click",function(){
console.log("tipItem
"+this.innerHTML+"
is clicked");
$(input).val(this.innerHTML);
_this.showTips(false);
});
};
}
发送打印数据
(1)点击打印
this.exportGrid =function(){
if (this.grid.store
== null) {
alert("尚未进行OD分析,无法导出表格");
return;
}
var data
= this.grid.store.data;
if
(data.length == 0) {
alert("尚未进行OD分析,无法导出表格");
return;
}
var
tempStr = "<Xml dateTimeStr='" + $("#spanDateTimeTips")[0].innerText
+ "'>";
for (var i =
0; i <= data.length - 1; i++) {
tempStr += "<Route
id='" + data[i].id + "' OriginName='" +
data[i].OriginName + "' DestinationName='" +
data[i].DestinationName + "' TransferName1='" +
data[i].TransferName1 + "' TransferName2='" +
data[i].TransferName2 + "' TransferName3='" +
data[i].TransferName3 + "' TransferName4='" +
data[i].TransferName4 + "' TransferName5='" +
data[i].TransferName5 + "' Directions='" +
data[i].Directions + "' Distance='" +
data[i].Distance + "' TimeCost='" +
data[i].TimeCost + "' StationCount='" +
data[i].StationCount + "' CheckOutNum='" +
data[i].CheckOutNum + "' ODPartition='" +
data[i].ODPartition + "' ODTotal='" +
data[i].ODTotal + "' Price='" +
data[i].Price + "' ></Route>";
}
tempStr += "</Xml>";
var
xmlHttp = null;
try {
xmlHttp = new XMLHttpRequest(); }
catch (e) {//
Internet Explorer
try {
xmlHttp = new
ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
xmlHttp = new
ActiveXObject("Microsoft.XMLHTTP");
}
}
xmlHttp.onreadystatechange = function () {
if (this.readyState
== 4 && this.status == 200) {//callback
var
xlsUrl = this.responseText;
document.getElementById("xlsLink").setAttribute("href",
xlsUrl);
document.getElementById("xlsLink").click();
//下载xls文件
unblockMapAppUI();
$("#imgExportExcel").removeClass("dNone");
}
else if (this.readyState
== 4 && this.status == 500) {
alert("服务端处理excel异常");
console.log(this.responseText);
console.log(this.responseXML);
}
};
var url =
"../ServerScript/Handlers/getODHandler.ashx?type=exportExcel&time=" + new
Date().toLocaleString();
xmlHttp.open("POST", url,
true);
xmlHttp.send(tempStr);
$("#imgExportExcel").addClass("dNone");
$blockUI({message:'<h1><img
src="../img/common.busy.gif"/> 查询中...</h1>'});
};
key事件发生顺序
结论:down-press-up
$("#mLogin-inUsr").on("keydown",function(e){
console.log("keydown");
});
$("#mLogin-inUsr").on("keyup",function(e){
console.log("keyup");
});
//inUsr
onChange
$("#mLogin-inUsr").on("keypress",function(e){
console.log("key
press");
});
keydown-值未变
结论:keydown发生时,值未变
$("#mLogin-inUsr").on("keydown",function(e){
console.log("keydown");
console.log($.trim($("#mLogin-inUsr").val()));
});
keypress-值未变
$("#mLogin-inUsr").on("keypress",function(e){
console.log("keypress");
console.log($.trim($("#mLogin-inUsr").val()));
});
keyup-值已变
$("#mLogin-inUsr").on("keyup",function(e){
console.log("keyup");
console.log($.trim($("#mLogin-inUsr").val()));
});
Array对象
数组,排序, 升序和降序,删除
升序:
function
sortFunction(a,b)
{
return
a - b
}
降序:
function
sortFunction (a,b)
{
return
b- a
}
调用方式:
ar.sort(sortFunction);
备注:执行后,数组顺序将改变
中文按拼音顺序排序
//按站名排序
var
sortGraphicsByName=function(b,a){
return b.attributes.NAME.localeCompare(a.attributes.NAME);
};
数组, pop和splice
Arr.pop() 删除并返回最后一个元素
Splice(i,1)删除第i个元素
删除1:
keys.splice(tempIndex, 1);//删除不限
备注:方法1得到的是剩余元素构成的数组。
删除2:
keys=keys.splice(tempIndex, 1);//删除不限
备注:方法2得到的是被删除元素形成的数组。
从数组中删除元素,loop必须用递减
数组拷贝
法1:
var arrB=arrA;
法2:
for(var i=0;i<=arrA.length-1;i++){
arrB.push(arrA[i]);
}
JS 数组合并排序
A:[1,3,5,7,9]
B:[1,3,6,8,10]
输出:
[1,3,5,6,7,8,9,10]
LocalStorage对象
只能存字符串
localStorage.setItem(‘test’,[1,2,3]);
取
localStorage.getItem(‘test’);
移除
localStorage.removeItem(‘test’);
Table对象
内存泄露
方案1:使用innerHTML清空table
添加900行后
Div.innerHTML=””之后
泄露大小:6M
泄露比率:6M/12M=50%
增删10次后内存:56M
每次增加比率:0.1/60.
方案2:使用deleteRow清空table
else if(e.target.id=="btnRemoveRows"){
var
tempTb=document.getElementById("tbMemoCheck");
for(var
i=tempTb.rows.length-1;i>=0;i--){
tempTb.deleteRow(i);
}
return false;
}
添加900行后:
DeleteRow之后:
泄露大小:6M
泄露比率:6M/12M=50%
增删10次后
泄露增值:7M-6M=1M;
每次增加比率:0.1/60.
结论:
使用innerHTML=””;
和deleteRow效率相同;
附录:代码
<style type="text/css">
#dvTableArea{
width:800px;
height:600px;
overflow:scroll;
}
#dvTableArea table{
border:1px
solid #000;
}
td{
border:1px
solid #000;
}
</style>
<script type="text/javascript">
window.onload=function(){
makeAndBind();
};
function clearRows(){
document.getElementById("dvTableArea").innerHTML="";
}
function appendRows(){
clearRows();
var innerString='<table
id="tbMemoCheck" cellSpacing="0px">';
for(var i=0;i<=900;i++){
innerString+='<tr>';
for(var j=0;j<=10;j++){
var cellText="cell("+i+","+j+")";
innerString+='<td>'+
cellText+'</td>';
}
innerString+='</tr>';
}
innerString+='</table>';
document.getElementById("dvTableArea").innerHTML=innerString;
}
//javascript 的 make and bind
function makeAndBind(){
document.body.onclick=function(e){
if(e.target.tagName.toLowerCase()=="td"){
console.log(e.target.innerHTML+"
is clicked");
return false;
}
else if(e.target.id=="btnAddRows"){
appendRows();
return false;
}
else if(e.target.id=="btnRemoveRows"){
clearRows();
return false;
}
return false;
}
}
</script>
</head>
<body class="tundra">
<div><input type="button" id="btnAddRows"
value="添加行"><input type="button" id="btnRemoveRows"
value="删除行"></div>
<div id="dvTableArea"></div>
</body>
</html>
Date对象
时刻差
结论:用于判断哪个方法执行时间长。 提高程序效率
var start=new
Date();
submit(url,
postData,function(rData){
var end=new
Date();
console.log("请求rData时间:"+(end.getTime()-start.getTime())+"毫秒");
DOM事件
绑定
备注:不依赖javascript框架,拓展性极强.
请优先于jquery和dojo的绑定方式使用
function bindEvents(){
document.getElementById("inpTest").onfocus=function(){
console.log("inpTest
is focused");
};
document.getElementById("inpTest").onblur=function(){
console.log("inpTest
is blured");
};
document.getElementById("inpTest").onclick=function(){
console.log("inpTest
is clicked");
};
/*不支持
document.getElementById("inpTest").onclick(function(){
console.log("inpTest
is clicked");
});
*/
document.getElementById("btnUnBind").onclick=function(){
}
}
取消绑定
键盘事件
onkeypress
<input type="text"
id="inpNameKey" value="关?键¨¹字Á?"
onkeypress="checkKey(event)"
Onkeydowm,onkeyup 连选选择
function allowContinSel(e) {
if (e.keyCode == 16) {
alert("允¨许¨连续选择");
}
}
function forbidenContinSel(e) {
if (e.keyCode == 16) {
alert("连续选择终止");
}
}
</script>
</head>
<body class="claro"
onkeydown="allowContinSel(event)" onkeyup="forbidenContinSel(event)">
On 绑定多次, Off关闭
<script type="text/javascript">
function bindClick(){
console.log("bindClick
is called");
//on("click"),
bind one, execute one. bind many times, execute manyTimes
$("#testDv").on("click",function(){
console.log("testDv
is clicked");
});
}
//off, many times before, no
on("click") after using off("click")
function unbind(){
$("#testDv").off("click");
}
$(document).ready(function(){
bindClick();
});
</script>
Console:
所有事件处理结束后 return false
Return false. 防止寻找其它handler
Blur事件 对象
序号 |
对象 |
是否能触发blue |
1 |
input type=”text” |
true |
input type=”button” |
||
2 |
span |
false |
label |
false |
冒泡和捕获
触发顺序
1. 当父元素和子元素都绑定了click,总是先触发最内层元素的click
2. 当只绑定了父元素click,通过e.target可以获取子元素
tr.click绑定 ,td.click绑定, 点击td
结论:
(1)td click后,会自动触发tr click
(2)在td.click 末尾添加 return false,可阻止tr.click
触发顺序是 最内层元素 依次向外
代码
<script type="text/javascript">
$(document).ready(function(){
bindUIEvents();
});
//情况1:
td tr都绑定了click事件,点击td。
//发生顺序:td.click,->tr.click。
//屏蔽方式:td.click
处理中添加
return false;
function
bindUIEvents(){
$(".row").on("click",function(e){
console.log("row is
clicked");
});
$("td").on("click",function(e){
console.log("td "+$(e.target)[0].innerHTML+"
is clicked");
return false;
});
}
</script>
<style>
td{border:1px
solid rgb(0,0,0);}
table{border-collapse:collapse;}
</style>
</head>
<body>
<table><tr class="row"><td class="col1">cell1</td><td class="col2">cell2</td><td class="col3">cell3</td></tr></table>
</body>
tr.click绑定,td不绑定,点击td
结论:
(1)tr.click被触发
(2)通过e.target可以获取到td
价值:
对大容器绑定一次, 容器里面的元素不绑定,通过r.target可在一个handler中处理所有事件。
//情况2:tr绑定click,td不绑定click。
//点击tr中的td,
tr.click触发,通过 e.target能获取到是哪个td被点击.
function
bindUIEvents(){
$(".row").on("click",function(e){
console.log("row is
clicked");
console.log("cell
is:"+$(e.target)[0].innerHTML);
});
}
<table><tr
class="row"><td class="col1">cell1</td><td
class="col2">cell2</td><td class="col3">cell3</td></tr></table>
阻止事件向父元素传播
子元素click中:
return
false;
DOM元素操作
删除
window.parent.document.body.removeChild(window.parent.document.getElementById("dvFrameOD"));
创建并绑定(入门)
说明:两种情况能找到创建的dom元素
-1.
Var domA=document.createElement(“div”);
domA.onclick=function(){}; //
-2.var
domB=document.createElement(“div”);
domB.innerHTML=”<input id=’input1’>”;
document.appendChild(domB);
//注意,append之后才能直接getElementById到
document.getElementById(“input1”).onclick=function(){
};
//javascript 的 make and bind
function makeAndBind(){
var operPane=document.createElement("div");
var innerString="";
for(var i=0;i<=2;i++){
var tempId='input'+i.toString();
var value='input'+i.toString();
innerString+='<input
type="text" value='+value+' id='+tempId+'>';
}
operPane.innerHTML=innerString;
document.getElementById("testDv").appendChild(operPane);
//备注:只有在append之后,getElementById才能获取到
for(var i=0;i<=2;i++){
if(document.getElementById("input"+i.toString())==null){
console.log("input"+i.toString()+"
is not found");
continue;
}
document.getElementById("input"+i.toString()).onclick=function(e){
console.log(e.target.id+"
is clicked");
};
}
}
创建并绑定 (一个容器,下辖多个元素)
说明:
创建div,div内用innerHTML创建3个input,
在div.onclick判断哪个子元素触发事件.
优点:只append一次.
只有一个onclick事件.
在appendChild之前也可绑定事件
适用于多层结构的情况
//javascript 的 make and bind
function makeAndBind(){
//div容器
var
operPane=document.createElement("div");
var innerString="";
//div容器 子元素html
for(var i=0;i<=2;i++){
var tempId='input'+i.toString();
var value='input'+i.toString();
innerString+='<input
type="text" value='+value+' id='+tempId+'>';
}
operPane.innerHTML=innerString;
//在div的click中处理所有子元素的事件
operPane.onclick=function(e){
var id=e.target.id;
if(id!=""){//子元素被点击
console.log(id+"
is clicked");
return false;
}
else{//div被点击
console.log("div
被点击");
return false;
}
}
//appendDiv
document.getElementById("testDv").appendChild(operPane);
}
创建并绑定(一个容器,下辖多个元素,元素下又辖元素)
三部曲:
-1 div.container=document.createElement(“div”);
-2 div.innerHTML=htmlString;
-3 div.onclick=function(e){
var targetId=e.target.id;
if(targetId==””){
}
Else if(){
}
}
备注:使用createElement创建的dom元素,在appendChild之前也可onclick
//javascript 的 make and bind
function makeAndBind(){
//div容器
var
operPane=document.createElement("div");
var innerString="";
//div容器 子元素html
for(var i=0;i<=2;i++){
var tempId='Level1-'+i.toString();
var value='Level1-'+i.toString();
if(i!=2){
innerString+='<div
type="text" value='+value+' id='+tempId+'>'+value+'</div>';
}
else{
innerString+='<div
type="text" value='+value+' id='+tempId+'>';
for(var j=0;j<=2;j++){
var tempId='Level2'+j.toString();
var value='Level2'+j.toString();
innerString+='<input
type="text" value='+value+' id='+tempId+'>';
}
innerString+='</div>';
}
}
operPane.innerHTML=innerString;
//在div的click中处理所有子元素的事件
operPane.onclick=function(e){
var id=e.target.id;
if(id!=""){//子元素被点击
console.log(id+"
is clicked");
return false;
}
else{//div被点击
console.log("大容器 被点击");
return false;
}
}
//appendDiv
document.getElementById("testDv").appendChild(operPane);
}
<body class="tundra">
<div id="testDv"></div>
</body>
清空元素下所有子节点
document.getElementById(graphicAddedTime).innerHTML="";
XMLHttpRequest和Ajax
AJAX军规
在url后面添加?time=一个不会重复的时间, 否则将受缓存影响
var
url = "http://localhost/ODWeb/getODHandler.ashx?type=&time=" +
new Date().toLocaleString();
xmlHttp.open("POST", url, true);
xmlHttp.send(postData);
AJAX GET
function sendReq() {
var xmlHttp = GetXmlHttpObject();
xmlHttp.onreadystatechange = function ()
{
if (this.readyState == 4) {
alert(this.responseText);
//call back snippets, use responseText for data
}
};
var url="photos.json";
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}
function GetXmlHttpObject() {
var xmlHttp = null;
try {
// Firefox, Opera 8.0+, Safari
xmlHttp = new XMLHttpRequest();
}
catch (e) {
// Internet Explorer
try {
xmlHttp = new
ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
xmlHttp = new
ActiveXObject("Microsoft.XMLHTTP");
}
}
return xmlHttp;
}
AJAX POST
function sendReq() {
var xmlHttp = GetXmlHttpObject();
xmlHttp.onreadystatechange = function () {
if (this.readyState == 4) {
alert(this.responseText);
//call back snippets, use responseText for data
}
};
var url = "../getODHandler.ashx";
xmlHttp.open("POST", url, true);
xmlHttp.send(postData);
}
function GetXmlHttpObject() {
var xmlHttp = null;
try {
// Firefox, Opera 8.0+, Safari
xmlHttp = new XMLHttpRequest();
}
catch (e) {
// Internet Explorer
try {
xmlHttp = new
ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
xmlHttp = new
ActiveXObject("Microsoft.XMLHTTP");
}
}
return xmlHttp;
}
AJAX军规,异步请求 线数据,站数据,时间数据
3种请求无前后关系,
ajax(“linedata”,function(){
bindlineEvent();});
ajax(“stationdata”,function(){
bindstationEvent();});
ajax(“stationdata”,function(){
bindyearEvent();});
AJAX军规-加时间,防止读缓存
在url后面添加?time=一个不会重复的时间, 否则将受缓存影响
var url = "http://localhost/ODWeb/getODHandler.ashx?type=&time="
+ new Date().toLocaleString();
xmlHttp.open("POST", url, true);
xmlHttp.send(postData);
动态Html字符串
动态background-position样式
$(document).ready(function(){
var htmlStr="";
for(var i=0;i<=9;i++){
htmlStr+='<div
style="background:url(../img/markers.png) 0px '+(-(i*25)).toString()+'px"></div>';
}
$("#testDiv").html(htmlStr);
});
备注:注意position数值,注意url引号。
效果
类和对象
Javascript 私有方法/公有方法
function testClass(){
this.publicHello=function(){
return "publicHello";
};
var
privateHello=function(){//私有方法,obj.privateHello无法调用
return "privateHello";
};
this.callPrivate=function(){
var
value=privateHello();
return
value;
};
this.callPrivate2=function(){
var
value=this.privateHello();//调用私有方法不能用this
return value;
};
}
/*调用举例
* var
testObj=new testClass();
*
testObj.publicHello(); //"publicHello";
*
testObj.privateHell():// undefined;
*
testObj.callPrivate(); //"privateHello";
*
testObj.callPrivate2(); //undefined;
*/
Javascript 访问公有成员(inside private M)
<html>
<head>
<title>private
method 调用成员,public method 调用成员</title>
<script type="text/javascript">
function
CTest(){
this.member="member
of CTest";
var
_this=this;
var
privateVisit=function(){
console.log("privateVisit,
this.member is:"+this.member);
console.log("privateVisit,_this.member
is:"+_this.member);
}
this.publicVisit=function(){
console.log("publicVisit,this.member
is:"+this.member);
}
this.callPrivateVisit=function(){
privateVisit();
console.log("callPrivateVisit
triggered privateVisit()");
}
}
</script>
</head>
<body>
<script type="text/javascript">
var
testObj=new CTest();
testObj.callPrivateVisit();
testObj.publicVisit();
</script>
</body>
</html>
控制台:
privateVisit, this.member is:undefined
privateVisit,_this.member is:member of CTest
callPrivateVisit
triggered privateVisit()
publicVisit,this.member is:member of CTest
Javascript 私/公 访调顺序
<html>
<head><title>私/公 声调顺序</title></head>
<script type="text/javascript">
function
CTest1(){
try{
privateLog();
var
privateLog=function(){
console.log("privateLog
has been called");
};
}
catch(e){
console.log(e.descripiton);
}
}
function
CTest2(){
try{
this.publicLog();
this.publicLog=function(){
console.log("publicLog
has been called");
};
}
catch(e){
console.log(e.description);
}
}
</script>
<body>
<script type="text/javascript">
var
test1=new CTest1();
var
test2=new CTest2();
</script>
</body>
</html>
控制台:
undefined
对象不支持“publicLog”属性或方法
结论:必须先声明,后调用
Javascript 调用私有方法
This.M(), _this.M() failed.
M() works;
<html>
<head><title>don't
use this.method to call private method</title></head>
<script type="text/javascript">
function
CTest1(){
var _this=this;
var privateA=function(){
console.log("privateA
has been called");
}
var
privateB=function(){
console.log("call
privateA()");
privateA();
console.log("\ncall
_this.privateA() in privateB");
try{
_this.privateA();
}
catch(e){
console.log(e.description);//_this.privateMethod()不能调用私有方法
}
};
privateB();//第一次执行privateB()
try//第二次执行privateB();
{
console.log("\ncall
this.privateB()");
this.privateB();
}
catch(e){
console.log(e.description);
}
}
</script>
<body>
<script type="text/javascript">
var
test1=new CTest1();
</script>
</body>
</html>
控制台:
call privateA()
privateA has been
called
call _this.privateA() in privateB
对象不支持“privateA”属性或方法
call this.privateB()
对象不支持“privateB”属性或方法
Javascript 类 (时刻,时间类)
//时º¡À刻¨¬
this.hour =
parseInt(h);
this.minute
= parseInt(m);
this.totalMinutes = this.hour * 60 + this.minute; //分¤?钟¨®总Á¨¹数ºy,ê?用®?于®¨²排?序¨°
return
this;
}
Moment.prototype.isSame = function (moment) {
if (this.hour == moment.hour && this.minute
== moment.minute) { return true; }
else { return false; }
}
Moment.prototype.isBefore = function (moment) {
if (this.hour < moment.hour) { return true; }
else if (this.hour == moment.hour) {
if (this.minute < moment.minute) { return true; }
else if (this.minute == moment.minute) { return
false; }
else { return false; }
}
else {
return false;
}
}
Moment.prototype.isAfter = function (moment) {
if (this.hour > moment.hour) { return true;
}//7:00. 7:01
else if (this.hour == moment.hour) {
if (this.minute > moment.minute) { return true; }
else if (this.minute == moment.minute) { return
false; }
else { return false; }
}
else {
return false;
}
}
//时段
function Period() {
if (arguments.length != 4 && arguments.length
!= 2) {return null;}
if (arguments.length == 4) {
var startH = arguments[0];
var startM = arguments[1];
var endH = arguments[2];
var endM = arguments[3];
if (startH > endH) { return null; }
else if (startH == endH) {
if (startM > endM) { return null; }
}
this.startMoment = new Moment(startH, startM);
this.endMoment = new Moment(endH, endM);
this.startMinutes = this.startMoment.totalMinutes;
this.endMinutes = this.endMoment.totalMinutes;
this.length = this.endMoment.totalMinutes -
this.startMoment.totalMinutes;
return this;
}
else {
this.startMoment = arguments[0];
this.endMoment = arguments[1];
this.startMinutes = this.startMoment.totalMinutes;
this.endMinutes = this.endMoment.totalMinutes;
this.length = this.endMoment.totalMinutes -
this.startMoment.totalMinutes;
return this;
}
}
/*
参数:
返回:
*/
Period.prototype.isSame = function (objPeriod) {
if
(this.startMoment.isSame(objPeriod.startMoment) &&
this.endMoment.isSame(objPeriod.endMoment)) { return true; }
else {
return false; }
}
Period.prototype.containMoment = function (moment) {
if
((this.startMoment.isSame(moment) || this.startMoment.isBefore(moment))
&& (this.endMoment.isSame(moment) || this.endMoment.isAfter(moment))) {
return true;
}
else {
return
false;
}
}
/*获取已选时段*/
function getPeriodArrayString(arrPeriods) {
var result
= "已°?选?时º¡À段?:";
arrPeriods.sort(sortPeriodsByStartMoment);
for (var i
= 0; i <= arrPeriods.length - 1; i++) {
result += arrPeriods[i].startMoment.hour +
":" + arrPeriods[i].startMoment.minute + "-" +
arrPeriods[i].endMoment.hour + ":" + arrPeriods[i].endMoment.minute +
",";
}
result =
result.substr(0, result.length - 1);
return
result;
}
JS时段合并
/*合并两个period
*/
function combineTowPeriod(last, prev) {
if (last.startMinutes > prev.endMinutes) {//左 离
return null;
console.log("0");
}
else if (last.startMinutes == prev.endMinutes) { //左共时刻
return (new Period(prev.startMoment, last.endMoment));
console.log("1");
}
//左部分相交
else if (last.startMinutes < prev.endMinutes &&
last.startMinutes > prev.startMinutes && last.endMinutes >
prev.endMinutes) {
return (new Period(prev.startMoment, last.endMoment));
console.log("2");
}
//真包含
else if (last.startMinutes <= prev.startMinutes &&
last.endMinutes >= prev.endMinutes) {
return (new Period(last.startMoment, last.endMoment));
console.log("3");
}
//右部分相交
else if (last.endMinutes > prev.startMinutes &&
last.endMinutes < prev.endMinutes) {
return (new Period(last.startMoment, prev.endMoment));
console.log("4");
}
//右共时刻
else if (last.endMinutes == prev.startMinutes) {
return (new Period(last.startMoment, prev.endMoment));
console.log("5");
}
//右 离
else if (last.endMinutes < prev.startMinutes) {
console.log("6");
return null;
}
else {
alert("预期外组合出现");
return null;
}
}
/*描述:时段区间合并算法
*/
function simplifyPeriodArray(arrPeriods) {
if (arrPeriods.length <= 1) {return arrPeriods;}
var haschanged = false;
do {
for (var j = arrPeriods.length - 1; j >= 0; j--) {
arrPeriods.sort(sortPeriodsByLength); //重新排序
haschanged = false;
var longestP = arrPeriods[j];//从尾取最长
for (var i = j-1; i >= 0; i--) {//合并j之前的i
var newP =
combineTowPeriod(longestP, arrPeriods[i]);
if (newP == null) { continue; }
else {
haschanged = true;
arrPeriods.splice(j, 1,
newP); //替换最长
longestP = newP;
arrPeriods.splice(i, 1);//删除被合并
}
}//end for
} //end for
}
while (haschanged);
}
JS 拷贝一个javascript对象/数组
背景:javascript对象都是引用类型.拷贝有两种方式:
方式1:重新构造javascript对象B,将A的属性逐个赋值到B上。
方式2:将A转成字符串,
创建对象B=JSON.parse(字符串)
下面介绍这种方式:
var jsonObj={x:101,y:102};
var tempObj=jsonObj;
tempObj.x=100;
console.log(jsonObj.x==tempObj.x);
var jsonStr=JSON.stringify(jsonObj);
var newObj=JSON.parse(jsonStr);
newObj.x=103;
console.log(jsonObj.x==newObj.x);
JS静态类 (JSON对象属性作为方法)
var staticClass={
sayHello:function(){
console.log("hello");
}
};
$(document).ready(function(){
staticClass.sayHello();
});
静态类方法A调用方法B
var staticClass={
sayHello:function(){
staticClass.getConstantPI();
},
getConstantPI:function(){
console.log(Math.PI);
}
};
拷贝/镜像应用
Copy步骤
1.找主页html,下载.
2. 从主页link和script建立对应的目录结构. 下载js,css文件
3.捕捉XMLHttpRequest Header头和url,data. 将reponseData存成json或者xml以供显示
Copy成果:
YYDA
应用举例
Script5 拒绝访问 (门户如何集成n个网站)
描述:
<html>
..<title>门户首页</title>..
…<iframe src=”跨域页.html”></iframe>..
</html>
<html>
..<title>跨域页.html</title>..
…<script
src=”jquery.js”></>...
<script
>
$(document).ready(function(){
});
</script>
</html>
报错;
Script
5:拒绝访问
$ 未定义
解决方式
<html>
..<title>门户首页</title>..
…<iframe src=”无jq跨域页.html”></iframe>..
</html>
<html>
..<title>无jq跨域页.html
</title>..
<iframe
src=”jq页.html”></iframe>
</html>
<html>
<title>jq页.html<title>
<script src=”jquery.js”></script>
<script>
$(document).ready(function(){
});
</script>
</html>
4800个点,智能获取首坐标
代码清单:
(1)autoObj
(2)startNextLoop
(3)autoBind
---
//自动绑定, 用控制台,未UI
autoObj:{
//localSearchOption
searchOption:{
//回调函数
onSearchComplete:function(results){
try{
var
resultStr="第"+shopMisUtil.autoObj.responseNum+"个响应,";
shopMisUtil.autoObj.responseNum++;
//获取发起shop
var
sourceKey=results.keyword;
var
sourceShop=function(){
for(var
j=0;j<=shopMisUtil.shops.length-1;j++){
if(shopMisUtil.shops[j].Address==sourceKey){
return
shopMisUtil.shops[j];
}
}
return null;
}();
//未找到地址
if
(results.getCurrentNumPois()==0){
sourceShop.Longitude=null;
sourceShop.Latitude=null;
resultStr+="\""+sourceKey+"\"未找到地址";
console.log(resultStr);
}
else{
//找到地址
sourceShop.Longitude=results.getPoi(0).point.lng;
sourceShop.Latitude=results.getPoi(0).point.lat;
resultStr+="\""+sourceKey+"\"坐标是:("+sourceShop.Longitude+","+sourceShop.Latitude+")";
console.log(resultStr);
}
//如果响应数目整数倍
var
modVal=shopMisUtil.autoObj.responseNum%shopMisUtil.autoObj.reqPerLoop;
if(modVal==0){
startNextLoop(shopMisUtil.autoObj.responseNum);
}
return;
}
catch(e){
alert(e.description);
return;
}
}
},
responseNum:0,//已经回应多少条
reqPerLoop:1000,//每轮请求多少个 100个占用350M内存,1000
450M
startNum:0,//从第几个开始绑定
maxNum:0,//找到第几个商店就不找了 0-
lengh-1
},
//自动绑定坐标
function autoBind(num){
//已绑定个数 0
shopMisUtil.autoObj.responseNum=0;
if(num==null){startNextLoop(0);}
else{startNextLoop(num);}
}
function
startNextLoop(fromNum){
var
toNum;
if(shopMisUtil.autoObj.maxNum!=0){
toNum=(fromNum+shopMisUtil.autoObj.reqPerLoop-1)<(shopMisUtil.autoObj.maxNum)?(fromNum+shopMisUtil.autoObj.reqPerLoop-1):(shopMisUtil.autoObj.maxNum);
}
else{
toNum=(fromNum+shopMisUtil.autoObj.reqPerLoop-1)<(shopMisUtil.shops.length-1)?(fromNum+shopMisUtil.autoObj.reqPerLoop-1):(shopMisUtil.shops.length-1);
}
console.log('startNextLoop
triggered, from '+fromNum+' to '+toNum);
for(var
i=fromNum;i<=toNum;i++){
var
oneShop=shopMisUtil.shops[i];
var
oneKey=oneShop.Address;
var
oneSearch=new BMap.LocalSearch(shopMisUtil.mp,shopMisUtil.autoObj.searchOption);
console.log("第"+i+"个地址\""+oneKey+"\"搜索开始");
oneSearch.search(oneKey);
}
}
4800个点,智能更新Oracle中坐标
原理:一次发送10个点。Ajax回调后,再发10个
为何只发10个:
发20个时,Svt中解析时出错,未查明原因。
代码:
updateObj:{
upNumPerLoop:10,//每次向tomcat更新多少个商店的位置,1次更新 //10, 480条/分钟
updatedNum:0//已更新位置
},
//更新所有商户位置
function
updateAllShops(){
var url="../ShopCudes";
//逐个发送
shopMisUtil.updateObj.updatedNum=0;
var
nextLoop=function(){
if(shopMisUtil.updateObj.updatedNum<shopMisUtil.shops.length){
var
tempAr=[];
var
tempNum=0;
var
cur=tempNum+shopMisUtil.updateObj.updatedNum;
while(tempNum<shopMisUtil.updateObj.upNumPerLoop&&cur<shopMisUtil.shops.length){
var
oneShop=shopMisUtil.shops[cur];
tempAr.push(oneShop);
tempNum++;
}
shopMisUtil.submit(url,{cmd:1,data:tempAr,condition:null},function(rData){
var
result=eval(rData)[0];
if(result.Done==true){
console.log("全商户,"+result.Info);
}
else{
console.log("全商户更新失败");
}
shopMisUtil.updateObj.updatedNum+=shopMisUtil.updateObj.upNumPerLoop;
nextLoop();
});
}
else{
console.log("全商户位置绑定完成");
}
};
nextLoop();
}
界面举例
组类UI处理方式
说明:
起点时段:shour,ehou,sminute,eminute,addedTimeO
终点时段:shour,ehou,sminute,eminute,addedTimeD
要进行的操作相同,仅仅DOM对象不同。
处理方式:设置5个对象,从界面条件,将5个对象指向。
var targetAddedTime = {};
var inpStartHour = {};
var inpStartMinute = {};
var inpEndHour = {};
var inpEndMinute = {};
var targetGraphicLayer = {};
if (this.id ==
"customOriginTime") {
targetAddedTime =
$("#addedTimeOrigin")[0];
inpStartHour =
$("#inpOHourStart")[0];
inpEndHour =
$("#inpOHourEnd")[0];
inpStartMinute =
$("#inpOMinuteStart")[0];
inpEndMinute =
$("#inpOMinuteEnd")[0];
targetGraphicLayer =
graLayerSelectO;
}
else {
targetAddedTime =
$("#addedTimeDestination")[0];
inpStartHour =
$("#inpDHourStart")[0];
inpEndHour =
$("#inpDHourEnd")[0];
inpStartMinute =
$("#inpDMinuteStart")[0];
inpEndMinute =
$("#inpDMinuteEnd")[0];
targetGraphicLayer =
graLayerSelectD;
}
后续语句将相同
报表样式设计
--1表头
--2左右有页边距
--3表头字体比表中数字明显
--4下页面有阴影效果
AMD 规范
概要
AMD= Asychronous Module Definition
异步模块规范。 作用是异步加载js类。比传统的(Legacy
Module Definition)效率高。
实现了AMD规范的js库有RequireJS 、curl 、Dojo 、bdLoad、JSLocalnet 、Nodules 等。
AMD require
用于加载js模块
举例:
require([module], callback);
第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。
举例:
require(['math'], function (math) { math.add(2, 3);});
math.add()与math模块加载不是同步的,浏览器不会发生假死。所以很显然,AMD比较适合浏览器环境。
AMD define
ASCII 128个
不可见:33个
可见:95个
字母 52个 |
数字行 26个 |
键盘右侧 16个 |
空格 1个 |
加密和解密
密码字符集
95个可显示字符中,除去空格。
即 94个
字母:52
数字行:26
右侧符号:16
结论:
不包含汉字
escape和unesace
escape原理:
(1)95个可显ASCII字符不变。其它字符变。
举例:
var psw="abcdefghijhlmnopqrstuvwxyz1234567890+-*/%!@#^&{}()<>.,;'你好";
var
esed=escape(psw);
var
unesed=unescape(esed);
console.log("escaped:"+esed);
console.log("unesed:"+unesed);
缺点:
(1)不加密字符数字
结论:
不用。
字符 和Unicode 转换
Unicode即万国码,全球所有字符。共65536个。
使用0-65535这些数值,建立字符-数值一一映射。
结论:比escape强,但需要进一步编码
charCodeAt-将字符转成 unicode数值
fromCharCode-将unicode数值转成 字符
//var str='1234qwER你好';
Str转UTF8数组
function
toUtf(str){
var result=[];
for(var i=0;i<=str.length-1;i++){
result.push(str.charCodeAt(i));
}
console.log(str +"
utf8:"+result);
return result;
}
UTF8数组转Str
function
toStr(arr){
var result="";
for(var i=0;i<=arr.length-1;i++){
result+=String.fromCharCode(arr[i]);
}
console.log(result);
return result;
}
1234qwER你好
utf8:49,50,51,52,113,119,69,82,20320,22909
[49, 50, 51, 52, 113, 119, 69, 82, 20320, 22909]
toStr(ar)
1234qwER你好
举例:
ende.encrypt("1234qweTFD你好");
[49, 50, 51, 52, 113, 119, 101, 84, 70, 68, 20320, 22909]
BCDEveWU佱妎
ende.decrypt("BCDEveWU佱妎")
1234qweTFD你好
sha256散列 密码
评定:
比plain Text安全。
其它网站账户安全。
引用:sha256.js
加密:
var
str="1234qwER你好世界";
sha256_digest(str)
"40dcee1b329f479172692e6213bbcf43d7c2229d49be5565ae811db3b84fb4ec"
结果:
64位的hash序列。
特点:不可逆
数据库存放hash序列,不存放密码