扩展jquery easyui datagrid编辑单元格
1.随便聊聊
这段时间由于工作上的业务需求,对jquery easyui比较感兴趣,根据比较浅薄的js知识,对jquery easyui中的datagrid的源码进行解读,想从中扩展一些实用方法出来.初次打开源码拜读时,呜呼呀,(用东北话说就是,哎呀妈呀),介些都是啥子玩意啊?原来,我从晚上下载的是min版的,众所周知,min版即为压缩版那啊,不过我先前以为只是将空格和回车删除掉了.出乎意料的是并非如此,各位请看:
1 function _195(_196, _197) { 2 var opts = $.data(_196, "progressbar").options; 3 var bar = $.data(_196, "progressbar").bar; 4 if (_197) { 5 opts.width = _197; 6 } 7 bar._outerWidth(opts.width)._outerHeight(opts.height); 8 bar.find("div.progressbar-text").width(bar.width()); 9 bar.find("div.progressbar-text,div.progressbar-value").css({height: bar.height() + "px", lineHeight: bar.height() + "px"}); 10 };
以上是我摘自1.8.0版本中的一段代码.可以看出,排版后仍然无法很轻易地阅读.在此插一句,如果各位谁有非min版本,请告之在下,在此感谢!
2.知识梳理
不过,在此也要告诉大家一个好小心,在本人的悉心研究下,已经有了重大突破!(怎么像发布会,抱歉抱歉),现在就将实践经验和代码呈上,请各位赐教!我所做的扩展是对单元格的操作,目前仅仅扩展了两个方法:beginEditCell和endEditCell,参照beginEdit和endEdit两个方法而来,有所改动还需完善.后者两个方法可以参照API,分别表示开始编辑一行和结束编辑一行,很显然这是针对可编辑的datagrid而言的.
扩展jquery有一个基本的框架,在这个框架之内是很普通写js代码是一样的的.下面看这个框架:
1 (function ($) { 2 $.extend($.fn.datagrid.methods, { 3 beginEditCell: function (target, options) { 4 return target.each(function () { 5 beginEditCell(this, options); 6 }); 7 }, 8 endEditCell: function (target, options) { 9 return target.each(function () { 10 endEditCell(this, options); 11 }); 12 } 13 }); 14 })(jQuery);
其中,代码中的beginEditCell和endEditCell就是我写的扩展方法,前者是开始编辑单元格,后者是结束编辑单元格. 下面简单介绍一下,juqery使用的引擎是sizzle,sizzle可以为你提供多元素操作,这也就是我提供的基本框架中有each的缘故了,并且还有将该元素返回,以便实现级联处理的效果.下面就把完整的代码展示出来,不做过多的解释,因为其中比较复杂,一一注释比较繁琐,不过有时间我会加上的.
(function ($) {
//开启编辑单元格状态
function beginEditCell(target, options) {
var opts = $.data(target, "datagrid").options;
var tr = opts.finder.getTr(target, options.index);
var row = opts.finder.getRow(target, options.index);
// //暂时还不知道该代码的含义,忽略使用
// if (tr.hasClass("datagrid-row-editing")) {
// return;
// }
// tr.addClass("datagrid-row-editing");
_initCellEditor(target, options.index, options.field);
_outerWidthOfEditable(target);
//$.validateRow(target, options.index);暂时先不使用,不知道该方法作用
}
function _initCellEditor(target, _index, _field) {
var opts = $.data(target, "datagrid").options;
var tr = opts.finder.getTr(target, _index);
var row = opts.finder.getRow(target, _index);
tr.children("td").each(function () {
var cell = $(this).find("div.datagrid-cell");
var field = $(this).attr("field");
if (field == _field) {//找到与传递参数相同field的单元格
var col = $(target).datagrid("getColumnOption", field);
if (col && col.editor) {
var editorType, editorOp;
if (typeof col.editor == "string") {
editorType = col.editor;
} else {
editorType = col.editor.type;
editorOp = col.editor.options;
}
var editor = opts.editors[editorType];
if (editor) {
var html = cell.html();
var outerWidth = cell._outerWidth();
cell.addClass("datagrid-editable");
cell._outerWidth(outerWidth);
cell.html("<table border="0" cellspacing="0" cellpadding="1"><tr><td></td></tr></table>");
cell.children("table").bind(
"click dblclick contextmenu",
function (e) {
e.stopPropagation();
});
$.data(cell[0], "datagrid.editor", {
actions: editor,
target: editor.init(cell.find("td"),
editorOp),
field: field,
type: editorType,
oldHtml: html
});
}
}
tr.find("div.datagrid-editable").each(function () {
var field = $(this).parent().attr("field");
var ed = $.data(this, "datagrid.editor");
ed.actions.setValue(ed.target, row[field]);
});
}
});
}
//为可编辑的单元格设置外边框
//来自jquery.easyui.1.8.0.js的 function _4d8()方法
function _outerWidthOfEditable(target) {
var dc = $.data(target, "datagrid").dc;
dc.view.find("div.datagrid-editable").each(function () {
var _this = $(this);
var field = _this.parent().attr("field");
var col = $(target).datagrid("getColumnOption", field);
_this._outerWidth(col.width);
var ed = $.data(this, "datagrid.editor");
if (ed.actions.resize) {
ed.actions.resize(ed.target, _this.width());
}
});
}
//关闭编辑单元格状态
function endEditCell(target, options) {
var opts = $.data(target, "datagrid").options;
var updatedRows = $.data(target, "datagrid").updatedRows;
var insertedRows = $.data(target, "datagrid").insertedRows;
var tr = opts.finder.getTr(target, options.index);
var row = opts.finder.getRow(target, options.index);
// //与beginEditCell相呼应,暂时取消
// if (!tr.hasClass("datagrid-row-editing")) {//行不能编辑时,返回
// return;
// }
// tr.removeClass("datagrid-row-editing");
var _535 = false;
var _536 = {};
tr.find("div.datagrid-editable").each(function () {
var _537 = $(this).parent().attr("field");
var ed = $.data(this, "datagrid.editor");
var _538 = ed.actions.getValue(ed.target);
if (row[_537] != _538) {
row[_537] = _538;
_535 = true;
_536[_537] = _538;
}
});
if (_535) {
if (_45f(insertedRows, row) == -1) {
if (_45f(insertedRows, row) == -1) {
updatedRows.push(row);
}
}
}
_destroyCellEditor(target, options);
$(target).datagrid("refreshRow", options.index);
opts.onAfterEdit.call(target, options.index, row, _536);
}
function _45f(a, o) {
for (var i = 0, len = a.length; i < len; i++) {
if (a[i] == o) {
return i;
}
}
return -1;
}
//销毁单元格编辑器
function _destroyCellEditor(target, options) {
var opts = $.data(target, "datagrid").options;
var tr = opts.finder.getTr(target, options.index);
tr.children("td").each(function () {
var field = $(this).attr("field");
if (field == options.field) {//找到与传递参数相同field的单元格
var cell = $(this).find("div.datagrid-editable");
if (cell.length) {
var ed = $.data(cell[0], "datagrid.editor");
if (ed.actions.destroy) {
ed.actions.destroy(ed.target);
}
cell.html(ed.oldHtml);
$.removeData(cell[0], "datagrid.editor");
cell.removeClass("datagrid-editable");
cell.css("width", "");
}
}
});
}
$.extend($.fn.datagrid.methods, {
beginEditCell: function (target, options) {
return target.each(function () {
beginEditCell(this, options);
});
},
endEditCell: function (target, options) {
return target.each(function () {
endEditCell(this, options);
});
}
});
})(jQuery);
测试页面也展示出来,方便大家使用,不过需要加上必需的jquery easyui代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Row Editing DataGrid - jQuery EasyUI Demo</title>
<link rel="stylesheet" type="text/css" href="../../themes/default/easyui.css">
<link rel="stylesheet" type="text/css" href="../../themes/icon.css">
<link rel="stylesheet" type="text/css" href="../demo.css">
<script type="text/javascript" src="../../jquery-1.8.0.js"></script>
<script type="text/javascript" src="../../jquery.easyui.min.js"></script>
<script type="text/javascript" src="../../plugins/jquery.datagrid.cellextend.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#dg").datagrid({
rownumbers:true,
iconCls: 'icon-edit',
singleSelect: true,
toolbar: '#tb',
url: '../datagrid/datagrid_data1.json',
onDblClickCell: onClickRow,
onAfterEdit:onAfterEdit,
striped:true,
columns:[[
{field: 'itemid', title: 'Item ID', 80, fitColumns: true},
{field: 'productid', title: 'Product', 100,
formatter: function (value, row) {
return row.productname;
},
editor: {
type: 'combobox',
options: {
valueField: 'productid',
textField: 'productname',
url: '../datagrid/products.json',
required: true
}
}},
{field: 'listprice', title: 'List Price', 80, align: 'right', editor: {type: 'numberbox', options: {precision: 1}}},
{field: 'unitcost', title: 'Unit Cost', 80, align: 'right', editor: 'numberbox'},
{field: 'attr1', title: 'Attribute', 250, editor: 'text'},
{field: 'status', title: 'Status', 60, align: 'center', editor: {type: 'checkbox', options: {on: 'P', off: ''}}},
{field: 'link', title: 'Link', 60, align: 'center',
formatter: function (value, rowData, rowIndex) {
return "<a href='" + value.href + "' onclick='test(" + rowIndex + ");return false;'>" + value.text + "</a>"
}
},
{field: 'isFamle', title: 'IsFamle', 60, align: 'center',
formatter: function (value, rowData, rowIndex) {
var str = value=="true" ? "checked" : "";
return "<input type='checkbox' " + str + ">";
//return "<a href='" + value.href + "' onclick='test(" + rowIndex + ");return false;'>" + value.text + "</a>"
}
}
]]
});
});
function test(obj){
alert(obj);
}
</script>
</head>
<body>
<h2>Row Editing DataGrid</h2>
<div class="demo-info">
<div class="demo-tip icon-tip"></div>
<div>Click the row to start editing.</div>
<a href="#">asdf</a>
</div>
<div style="margin:10px 0;"></div>
<table id="dg" class="easyui-datagrid" title="Row Editing DataGrid" style="800px;height:auto">
<thead>
<tr>
</tr>
</thead>
</table>
<script type="text/javascript">
var _rowIndex = undefined;
var _field = undefined;
function endEditing() {
if (_rowIndex == undefined || _field == undefined) {
return true;
}
$('#dg').datagrid('endEditCell', {index: _rowIndex, field: _field});
_rowIndex = undefined;
_field = undefined;
return true;
}
function onClickRow(rowIndex, field, value) {
//$('#dg').datagrid('beginEdit', rowIndex);
//$('#dg').datagrid('getEditors', rowIndex);
if (_rowIndex != rowIndex || _field != field) {
if (endEditing()){
$('#dg').datagrid('beginEditCell', {index: rowIndex, field: field});
_rowIndex = rowIndex;
_field = field;
}
}
var data = $('#dg').datagrid('getSelected');
// alert(data.link.href);
}
function onAfterEdit(rowIndex, rowData, changes){
if(changes.status=="P"){
rowData["attr1"]="12312312";
$('#dg').datagrid('updateRow',{
index: rowIndex,
row: rowData
});
$('#dg').datagrid('acceptChanges');
var data = $('#dg').datagrid('getSelected');
alert(data.status);
}else if(changes.status==""){
rowData["attr1"]="12312312";
$('#dg').datagrid('updateRow',{
index: rowIndex,
row: rowData
});
$('#dg').datagrid('acceptChanges');
var data = $('#dg').datagrid('getSelected');
alert(data.status);
alert(data.attr1);
}
}
</script>
</body>
</html>
感谢大家阅读,请多指教!谢谢
CSS media queries
最近在做一些页面打印时的特殊处理接触到了media queries,想系统学习一下,在MOZILLA DEVELOPER NETWORK看到一篇文章讲的很不错,结合自己的使用总结一下。
CSS2/media
在CSS2中可以使用media属性可以使特定style只在指定媒体类型下其作用,比如页面有些部分需要在打印的时候隐藏或者变大,这时候可以使用media使某些style只在打印的时候生效
@media print { /* 适用于印刷的样式 */ }
<link href="css/print.css" rel="stylesheet" type="text/css" media="print" />
常用的媒体类型有
- all(所有),适用于所有设备。
- handheld(手持),用于手持设备。
- print(印刷),用于分页材料以及打印预览模式下在屏幕上的文档视图。
- projection(投影),用于投影演示文稿,例如投影仪。
- screen(屏幕) ,主要用于计算机屏幕。
在使用的时候可以在样式表直接书写 @media指令+空格+媒体类型(多个都好隔开)
@media print { body { font-size: 10pt } } @media screen { body { font-size: 13px }parsing-errors } @media screen, print { body { line-height: 1.2 } }
CSS3/meidia queries
在CSS3中对其进行了增强,添加了更多的媒体查询,CSS3中的Media Queries增加了更多的媒体查询,同时可以添加不同的媒体类型的表达式用来检查媒体是否符合某些条件,比如如果网页用PC访问和Pad访问使用不同的style,在CSS2中只能把媒体类型设为screen是不能做到的,而在CSS3中可以对screen类型媒体设置表达式进一步判断屏幕大小来实现这一功能。可以写出这样的代码
<!-- CSS media query on a link element --> <link rel="stylesheet" media="(max- 800px)" href="example.css" /> <!-- CSS media query within a style sheet --> <style> @media (max- 600px) { .facet_sidebar { display: none; } } </style>
当媒体类型匹配且表达式为真的时候,对应style就会其作用,除非使用not或者only操作符,否则媒体类型不是必需的,默认代表所有媒体类型。
操作符
and
and操作符用于将多个media feature组合成一个查询,同时用于组合media type 和media feature,一个基本的media query类似这样,一个meidia feature作用于所有media type
@media (min- 700px) { ... }
但是如果只想在横向显示时应用就可以使用and操作符把media type和media feature结合起来
@media (min- 700px) and (orientation: landscape) { ... }
这样上面的media query只有在可视窗口(viewport)最小是700px并且是横向显示的时候才返回true,如果还想进一步限制设备为tv可以这样
@media tv and (min- 700px) and (orientation: landscape) { ... }
逗号分隔的列表
在使用逗号分隔的查询列表中每个查询都被视为一个独立的查询,任何本查询中的作用符不影响其他查询,只要有一个查询返回true,style就会被作用。
举例来说,如果希望特定style在viewport最小宽度为700px或手持式设备上生效,可以这么写:
@media (min- 700px), handheld and (orientation: landscape) { ... }
not
not操作符作用域整个查询,所以只有在整个查询返回false的情况下使用not后才会返回true。当使用逗号分隔的列表的时候not作用于邻近的查询,而不会作用于每个查询
@media not all and (monochrome) { ... }
查询其实会这样起作用
@media not (all and (monochrome)) { ... }
而不是这样
@media (not all) and (monochrome) { ... }
对于逗号分隔的列表
@media not screen and (color), print and (color)
查询是这样子的
@media (not (screen and (color))), print and (color)
only
only操作符用于阻止不支持带有media feature的media queries的浏览器应用特定style
<link rel="stylesheet" media="only screen and (color)" href="example.css" />
media features
说了好多次media feature了,到底有多少个media feature呢
-
1、width:浏览器宽度
-
2、height:浏览器高度
-
3、device-width:设备屏幕分辨率的宽度值
-
4、device-height:设备屏幕分辨率的高度值
-
5、orientation:浏览器窗口的方向纵向还是横向,当窗口的高度值大于等于宽度时该特性值为portrait,否则为landscape。
-
6、aspect-ratio:比例值,浏览器的纵横比.
-
7、device-aspect-ratio:比例值,屏幕的纵横比.
-
8、color:设备使用多少位的颜色值,如果不是彩色设备,值为0
-
9、color-index:色彩表的色彩数
-
10、monochrome:单色帧缓冲器每个像素的字节
-
11、resolution:分辨率值,设备分辨率值
-
12、scan:电视机类型设备扫描方式,progressive或interlace
-
13、grid:只能指定两个值0或1
-
如何引入media
有两种常用的引入方式
1、link方法引入
<link rel="stylesheet" type="text/css" href="styleB.css" media="screen and (min- 600px) and (max- 800px)">
2、@media引入
@media screen and (min- 600px) and (max- 800px){ 选择器{ 属性:属性值; } }
浏览器兼容性
应用
For iPhone 4
<link rel="stylesheet" media="only screen and (-webkit-min-device-pixel-ratio: 2)" type="text/css" href="iphone4.css" />
For iPad
<link rel="stylesheet" media="all and (orientation:portrait)" href="portrait.css">
<link rel="stylesheet" media="all and (orientation:landscape)" href="landscape.css">
移动设备iPad上的Safari和在iPhone上的是相同的,只是他们不同之处是iPad声明了不同的方向,比如说上面的例子,在纵向(portrait)时采用portrait.css来,在横向(landscape)时采用landscape.css。
For Android
/*240px的宽度*/ <link rel="stylesheet" media="only screen and (max-device-240px)" href="android240.css" type="text/css" /> /*360px的宽度*/ <link rel="stylesheet" media="only screen and (min-device-241px) and (max-device-360px)" href="android360.css" type="text/css" /> /*480px的宽度*/ <link rel="stylesheet" media="only screen and (min-device-361px) and (max-device-480px)" href="android480.css" type="text/css" />
参考
http://www.w3cplus.com/content/css3-media-queries
http://www.w3cplus.com/css3/css3-media-queries-for-iPhone-and-iPads
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries