表格排序
比tablesorter功能少 但灵活 可以根据实际需求做调整
本来用tablesorter做需求 但改的太费劲了 自己做了一个
<head>中添加
<title></title>
<link rel="stylesheet" href="/blog_article/style.css" type="text/css" media="print, projection, screen" />
<script type="text/javascript" src="/blog_article/jquery-1.7.1.js"></script>
<script type="text/javascript" src="/blog_article/tableOrder.js"></script>
</head>
表格形式 每行的 <td >1</td> 是用来还原本来顺序的
<thead>
<tr>
<th >
</th>
<th id="t1h1">
表1-排序1
</th>
<th id="t1h2">
表1-排序2
</th>
<th id="t1h3">
表1-排序3
</th>
</tr>
</thead>
<tbody>
<tr>
<td >
1
</td>
<td>
200
</td>
<td>
300
</td>
<td>
500
</td>
</tr>
<tr>
<td >
2
</td>
<td>
100
</td>
<td>
400
</td>
<td>
200
</td>
</tr>
<tr>
<td >
3
</td>
<td>
100
</td>
<td>
600
</td>
<td>
800
</td>
</tr>
<tr>
<td >
4
</td>
<td>
300
Dojo Grid 结构
Dojo Grid 在结构上有点类似于大家熟悉的 MVC 模式。MVC 模式是“Model-View-Controller”的缩写,也就是“模型 - 视图 - 控制器”。
图 1.MVC 结构
一个最简单的 Grid 在结构上主要有以下几方面构成:
模型 (Model)
每个 Grid 都会包含数据,所以每个 Grid 开头都会去定义 Model。如清单 1 中的定义,Model 包含了 dojotype(dojo 模型类),jsid(专用 id),structure(结构),Store(数据库)等。 其中比较重要的部分是 Store,它放置了 Grid 中存储的数据。
清单 1. Grid 的定义
canSort="false" structure="modelGridLayout" Store="modelStore"></div>
视图 (View) 和结构 (Structure)
View 用来定义每个数据列,一个 View 是多个数据列的组合。通过定义 View,使 Grid 按照要求来显示数据。 Structure 是 View 的集合,也就是说可以将多个 View 组合成一个 Structure。Structure 会被 Grid 用到,而 View 不会被 Grid 直接用到, 而是被包装成一个 Structure 来使用。清单 2 中是一个 Grid Layout 的范例,它定义了 Grid 的结构。cells 部分定义了 Grid 列定义的信息。 每一列需要定义 name、id、field,以及列的 html 形式如长宽高之类的。之后对 Grid 列的操作主要是针对 field 域。
清单 2. Grid Layout 的定义
cells: [
{ name:'<div ><input type="checkbox"
onclick="DeviceGridRevertSelectAll(this)" id="checkcollection"></div>',
field: 'Sel', editable: true, width: '20px', cellStyles: 'text-decoration: none;
cursor:default; text-align: center;position: relative; left: -10px', headerStyles:
'text-align: center;', type: dojox.grid.cells.Bool },
{ name: 'Model',field: 'Model', width: '170px',cellStyles:'font-size:9pt;
cursor: default;text-align: left;', cellClasses: 'defaultColumn', headerStyles:
'text-align: center;'},
{ name: 'Device',field: 'Device', width: '150px', cellStyles: 'font-size: 9pt;
font-style:normal,text-decoration: none; cursor:default;text-align: left;',
cellClasses: 'defaultColumn', headerStyles: 'text-align: center;'},
]
}];
Grid 控件 (Widget)
这里的 Grid 控件类似于 MVC 中的控制器(Control)。通过 Grid 各种预先定义的 API 对 Grid 的数据(Model), 视图(View)有效的组织起来,并进行操作。以达到有效控制 Grid 数据存取、更新、外观变化的目的。 从而显示出一个类似于电子表格的 Grid 列表。
Dojo Grid 的数据存储
在 Grid Model 的定义中,有一个叫 Store 的属性,它存储了与 Grid 相关联的数据,也就是 Grid 绑定到的数据源。 在示例中,数据源的名字叫 modelStore。modelStore 的定义如下:
Dojo 的核心提供了一个只读的数据体实现,ItemFileReadStore。这个数据体可以从 HTTP 端点读取 Json 结构体,或是读取内存中的 JavaScript 对象。 Dojo 允许为 ItemFileReadStore 指定某个属性来作为 identifier(唯一标识符)。Dojo 内核同时提供了 ItemFileWriteStore 存储作为 ItemFileReadStore 的一个扩展,它是建立在 dojo.data.api.Write 和 dojo.data.api.Notification API 对 ItemFileReadStore 的支持之上的。如果你的应用程序需要 写入数据到 ItemFileStore,则 ItemFileWriteStore 正是你所要的。
对于 Store 的操作,可以使用函数 newItem, deleteItem, setValue 来修改 Store 的内容,这些操作可以通过调用 revert 函数来取消, 或者调用 save 函数来提交修改。
在使用这些函数时,一定要注意的是,如果你为 ItemFileWriteStore 指定了某个属性来作为 identifier,必须要确保它的值是唯一的, 这对 newItem 和 deleteItem 函数特别重要,ItemFileWriteStore 使用这些 ID 来跟踪这些改变,这意味着即使你删除了一个 Item, 它的 identity 还是被保持为使用状态,因此,如果你调用 newItem() 并试图重用这个 identifier,你将得到一个异常。要想重用这个 identifier, 你需要通过调用 save() 来提交你的改变。Save 将应用所有当前的改变并清除挂起的状态,包括保留的 identifier。当你没有为 Store 指定 identifier 时, 则不会出现上述问题。原因是,Store 会为每个 Item 自动创建 identifier,并确保了它的值是唯一的。在这种自动创建 identifier 的情况下, identifier 是不会作为一个公有属性暴露出来的(它也不可能通过 getValue 得到它,仅 getIdentity 可以)。
Store 的数据存储在两个 json 数组中,名字分别为 _arrayOfAllItems 和 _arrayOfTopLevelItems。这两个数组的区别是在于前者记录了 Grid 创建以来 Store 中存在过的所有变量, 后者中只是存储 Store 当前的所有 Item。如果有变量被删除,则 _arrayOfAllItems 中该数组变量设为 null,而 _arrayOfTopLevelItems 中该数组变量会被彻底删除, 数组个数减一。这样的设定是为了在 Store.newItem 的时候,如果用户没有为 Store 指定 identifier,Store 可以自动地用 _arrayOfAllItems 的数量值为新 Item 创建 identifier。_arrayOfAllItems 的个数不会因为删除操作而减少,也就不必担心新 Item 的 identifier 就会发生重复。
程序清单 3 中描述了 Grid 自动创建 identifier 的过程,首先程序会尝试去获得之前定义的 Identifier 属性。如果属性是 Number 就把 _arrayOfAllItems.length 赋给 newIdentity。如果属性不是 Number, 就把 identifierAttribute 对应的 keywordArgs 赋给 newIdentity,如果 newIdentity 是空,就表示 identity 创建失败。
清单 3. Grid identifier 的创建
var identifierAttribute = this._getIdentifierAttribute();
if(identifierAttribute === Number){
newIdentity = this._arrayOfAllItems.length;
}
else{
newIdentity = keywordArgs[identifierAttribute];
if (typeof newIdentity === "undefined"){
throw new Error("newItem() was not passed an identity for the new Item");
}
}
图 2 则显示了当删除一个数据后,_arrayOfAllItems 和 _arrayOfTopLevelItems 的差别
学习javascript时最困惑的就是函数及其作用域,钻研了这么久也有了一些心得,以下为个人见解,如果有错误请指出,谢谢~
本文中没有讨论通过Function()构造函数创建函数时的情况,因为这种情况下会动态地创建和编译javascript代码,并且创建出来的函数并不使用词法作用域(请参考《JavaScript权威指南》),而是被当作顶级函数来编译。
作用域指的是一个抽象的范围,如果解析一个变量名时能够找到它则说明这个变量存在于这个作用域中。而具体查找的过程则是顺着作用域链从头到尾来查找的。
先来看一段代码,默认在全局作用域内执行,方便起见可以直接在Firebug控制台执行:
var b=1;
function F(x)
{
var b=0;
arguments.callee.c=1;
alert(F.c);
alert(F.e);
alert(arguments.callee === F);
function G(y){
alert(y);
alert(F.e);
};
G(2);
}
F.e=0;
我们知道每个javascript执行环境都有一个和它相关联的作用域链,在顶层代码中(不属于任何函数定义的代码),作用域链只由一个对象构成,即全局对象。因此执行之后作用域链就是全局对象,如下所示(注意我们这时候只是定义了函数,但并没有执行):
接下来进入重点了,执行以下代码:
在执行一个函数时,会根据函数体创建一个调用对象并且把它添加到作用域链的头部,并且更新指向作用域链头部的指针为新创建的调用对象。函数体内部通过var语句声明的局部变量,有名称的嵌套函数以及函数的形式参数都是这个调用对象的属性。此时作用域链如下所示:
注意F引用的是函数对象,不是调用对象(从作用域链头部开始解析“F”,在全局对象中找到了“F”)。调用对象的属性arguments具有特殊的作用,arguments.callee引用的是该函数的函数对象,即F。因此执行
函数对象F增加了一个属性c,并且定义了嵌套函数G,此时作用域链如下:
因此执行
alert(F.e);
依次显示1,0。并且执行
显示true。
执行
由于调用了函数,因此又创建了新的调用对象并且添加到作用域链头部,此时作用域链如下:
所以执行
alert(F.e);
分别显示2,0。
每当退出一个函数便会移除并销毁相对应的调用对象(因为没有任何引用了,所以被垃圾回收了),作用域链也就恢复到了之前的状态,形成了一种类似堆栈的效果。
最后来看一下闭包,执行以下代码:
var id=0;
function G(){
return id++;
}
return G;
}
var H=F();
执行完毕之后虽然已经退出了函数,但是其调用对象依旧存在,因为全局对象H引用了其内部的函数(弧形箭头所示),如下:
然后执行
注意此时由于H引用的是G,因此指向作用域链头部的指针会从指向全局对象直接改变为指向根据G函数新创建的调用对象B,B成为了作用域链的头部,然后是之前就已经存在的调用对象A和全局对象。作用域链如下:
退出函数之后指向作用域链头部的指针则又重新指向了全局对象,B会被垃圾回收销毁,但是A依然会存在,因为仍然有H引用。
本文链接