公共的JS组件-告别CURD
urls.py
urlpatterns = [
url('^asset.html$', views.AssetView.as_view()),
url('^asset-json.html$', views.AssetJsonView.as_view()),
]
views.py
# CBV方式
class AssetView(View):
def get(self,request,*args,**kwargs):
# 数据库中获取数据
return render(request, 'asset.html') class AssetJsonView(View):
def get(self,request,*args,**kwargs):
table_config = [
{
'q': None,
'title': '选项',
'display': True,
'text': {'content':'<input type="checkbox" />','kwargs': {}},
'attrs': {},
},
{
'q':'id',
'title':'ID',
'display':False,
'text':{},
'attrs':{},
},
{
'q': 'asset_type_id',
'title': '资产类型',
'display': True, # 是否显示
'text': {'content': '{n}', 'kwargs': {'n': '@@asset_type_choices', }},
'attrs': {},
},
{ # 'edit-type': 'select'可编辑时变成下拉框
'q': 'status_id',
'title': '状态',
'display': True, # 是否显示
'text': {'content': '{n}', 'kwargs': {'n': '@@status_choices',}},# 双@表示找选项里对应的内容
'attrs': {'name':'status_id','origin':'@status_id','edit-enable': 'true', 'edit-type': 'select','global-name':'status_choices'},
},
{
'q': 'idc__id',
'title': '机房ID',
'display': False,
'text': {},
'attrs': {},
},
{
'q': 'idc__name', # 一对多跨表操作
'title': '机房',
'display': True, # 是否显示
'text': {'content': '{n}', 'kwargs': {'n': '@idc__name', }},# 一个@表示取数据库中的信息
'attrs': {'name':'idc_id','origin':'@idc__id','edit-enable': 'true', 'edit-type': 'select','global-name':'idc_choices'},
},
{
'q': 'cabinet_num',
'title': '机柜号',
'display': True,
'text': {'content':'{n}','kwargs':{'n':'@cabinet_num'}},
'attrs': {'name':'cabinet_num','origin':'@cabinet_num','edit-enable': 'true', 'edit-type': 'input'},
},
{
'q': 'cabinet_order',
'title': '机柜位置',
'display': True,
'text': {'content': '{n}', 'kwargs': {'n': '@cabinet_order'}},
'attrs': {},
},
{
'q': None, # 表示不去数据库取数据
'title': '操作',
'display': True,
'text': {'content': '<a href="/asset_detail-{m}.html">{n}</a>', 'kwargs': {'m':'@id','n':'详细'}},
'attrs': {},
},
]
q_list = []
for i in table_config:
if not i['q']:
continue
q_list.append(i['q'])
data_list = Asset.objects.all().values(*q_list)
data_list = list(data_list)
print(data_list) # [{'id': 1, 'cabinet_num': '12B', 'cabinet_order': '1'}]
result = {
'table_config':table_config,
'data_list':data_list,
'pager':'''
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
''',
'global_dict':{
'asset_type_choices': Asset.asset_type_choices, # json处理之后,元组会变成列表
'status_choices': Asset.status_choices,
'idc_choices': list(IDC.objects.values_list('id','name')),
},
}
return HttpResponse(json.dumps(result)) def put(self,request,*args,**kwargs):
# 没有request.post
content = request.body
val = json.loads(str(content,encoding='utf-8'))
ret = {'status':True}
return HttpResponse(json.dumps(ret))
html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>后台管理</title>
{% load staticfiles %}
<link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.css' %}"/>
<link rel="stylesheet" href="{% static 'plugins/font-awesome/css/font-awesome.css' %}"/>
</head>
<body>
<div style="width: 1000px;margin: 0 auto;">
<h1>资产列表</h1>
<div class="btn-group" role="group" aria-label="...">
<button id="idCheckAll" type="button" class="btn btn-default">全选</button>
<button id="idReverseAll" type="button" class="btn btn-default">反选</button>
<button id="idCancelAll" type="button" class="btn btn-default">取消</button>
<button id="idEditMode" type="button" class="btn btn-default">进入编辑模式</button>
<button type="button" class="btn btn-default">批量删除</button>
<a id="idAdd" href="asset_add.html" class="btn btn-default">添加</a>
<button id="idSave" type="button" class="btn btn-default">保存</button>
</div>
<table class="table table-bordered">
<thead id="table_th">
</thead>
<tbody id="table_tb">
</tbody>
</table>
<ul id="idPagination" class="pagination">
</ul>
</div>
<script src="{% static 'js/jquery-3.3.1.js' %}"></script>
<script src="{% static 'js/nbList.js' %}"></script>
<script>
$(function () {
$.NB('/asset-json.html');
});
</script>
</body>
</html>
公共JS组件:主要是调用扩展方法NB
(function () {
var requestUrl = null;
//绑定分页事件
function bindChangePager(){
$('#idPagination').on('click','a',function () {
var pageNum = $(this).text();
init(pageNum);
})
}
//保存
function bindSave() {
$('#idSave').click(function () {
//找到有hasEdit属性的tr标签
var postList = [];
$('#table_tb').find('tr[has-edit="true"]').each(function () {
//$(this)=tr
var temp = {
/*
'id':1,
'status':1,
'order':12,*/
};
temp['id'] = $(this).attr('row-id');
$(this).children('[edit-enable="true"]').each(function () {
//$(this)=td
var name = $(this).attr('name'); //'name':'cabinet_num'
var origin = $(this).attr('origin');
var newVal = $(this).attr('new-val');
if(origin != newVal){
temp[name] = newVal; //'idc_id':2 新的select的value
}
});
postList.push(temp);
});
$.ajax({
url:requestUrl,
type:'PUT',
data:{'post_list':JSON.stringify(postList)},
dataType: 'JSON',
success:function (arg) {
if(arg.status){
init(1); //初始化到第一页
}else{
alert(arg.error);
}
}
})
})
}
//全选
function bindCheckAll() {
$('#idCheckAll').click(function () {
$('#table_tb').find(':checkbox').each(function () {
if($('#idEditMode').hasClass('btn-warning')){
if($(this).prop('checked')){
//如果当前行已经进入了编辑模式
}else{
trIntoEditMode($currentTr = $(this).parent().parent());
$(this).prop('checked',true);
}
}else{
$(this).prop('checked',true);
}
})
})
}
//取消
function bindCancelAll() {
$('#idCancelAll').click(function () {
$('#table_tb').find(':checked').each(function () {
if($('#idEditMode').hasClass('btn-warning')){
$(this).prop('checked',false);
//取消选中,并退出编辑模式
trOutEditMode($(this).parent().parent());
}else{
$(this).prop('checked',false);
}
});
})
}
//反选
function bindReverseAll() {
$('#idReverseAll').click(function () {
$('#table_tb').find(':checkbox').each(function () {
if($('#idEditMode').hasClass('btn-warning')){
if($(this).prop('checked')){
//如果已经进入编辑模式,选中的要取消,再退出编辑
$(this).prop('checked',false);
trOutEditMode($(this).parent().parent());
}else{
//如果已经进入编辑模式,未选中的要选中,再进入编辑
$(this).prop('checked',true);
trIntoEditMode($(this).parent().parent());
}
}else{
if($(this).prop('checked')){
$(this).prop('checked',false);
}else{
$(this).prop('checked',true);
}
}
})
})
}
//点击进入或退出编辑模式
function bindEditMode(){
$('#idEditMode').click(function () {
if($(this).hasClass('btn-warning')){
//退出编辑模式
$(this).removeClass('btn-warning');
$(this).text('进入编辑模式');
//找到所有选中的tr,进入编辑模式
$('#table_tb').find(':checked').each(function () {
var $currentTr = $(this).parent().parent();
trOutEditMode($currentTr);
})
}else{
//进入编辑模式
$(this).addClass('btn-warning');
$(this).text('退出编辑模式');
//找到所有选中的tr,退出编辑模式
$('#table_tb').find(':checked').each(function () {
var $currentTr = $(this).parent().parent();
trIntoEditMode($currentTr);
})
}
})
}
//委托绑定:如果用ajax在页面上添加了一行数据,会自动绑定这个事件
function bindCheckbox(){
$('#table_tb').on('click',':checkbox',function () {
if($('#idEditMode').hasClass('btn-warning')){
var ck = $(this).prop('checked');
var $currentTr = $(this).parent().parent(); //变量前带$的表示为jQuery对象,只是自己看着方便
if(ck){
//选中状态,进入编辑,给tr加上背景色
trIntoEditMode($currentTr);
}else{
trOutEditMode($currentTr);
}
}
})
}
//选中,进入编辑模式
function trIntoEditMode($tr){
$tr.addClass('success');
$tr.attr('has-edit','true'); // 只要进入过编辑状态的,都加上这个属性
$tr.children().each(function () {
//$(this)就是tr的每一个孩子td
var editEnable = $(this).attr('edit-enable'); //检查当前是否是可编辑模式
var editType = $(this).attr('edit-type');
if(editEnable == 'true'){
//可以进入编辑模式
if(editType == 'select'){
//生成下拉框
var globalName = $(this).attr('global-name'); //global-name = status_choices
var origin = $(this).attr('origin'); //
//生成select标签
var selectTag = document.createElement('select');
selectTag.className = 'form-control';
$.each(window[globalName],function (k1,v1) {
var optionTag = document.createElement('option');
optionTag.setAttribute('value',v1[0]);
optionTag.innerHTML = v1[1];
$(selectTag).append(optionTag);
});
$(selectTag).val(origin);
$(this).html(selectTag);
}else if(editType == 'input'){
//生成input框
var innerText = $(this).text();
var tag = document.createElement('input');
tag.className = 'form-control';
tag.style.width = '100%';
tag.value = innerText;
$(this).html(tag);
}
}
})
}
//取消选中,退出编辑模式
function trOutEditMode($tr){
$tr.removeClass('success');
$tr.children().each(function () {
//$(this)就是tr的每一个孩子td
var editEnable = $(this).attr('edit-enable'); //检查当前是否可编辑
var editType = $(this).attr('edit-type');
if(editEnable == 'true'){
//如果是可编辑的
if(editType == 'select'){
//如果是select框
var $select = $(this).children().first(); //jQuery对象
var newId = $select.val(); //选中的option的id
var newText = $select[0].selectedOptions[0].innerHTML;//选中的option的text
$(this).html(newText); //用文本替换原来的select框
$(this).attr('new-val',newId); //设置新的value值
}else{
var inputVal = $(this).children().first().val(); //获取input的值
$(this).html(inputVal);
$(this).attr('new-val',inputVal);
}
}
})
}
//自定义string方法,字符串格式化
String.prototype.format = function (kwargs) {
return this.replace(/\{(\w+)\}/g,function (km,m) {
return kwargs[m];
})
};
//初始化
function init(pager) {
$.ajax({
url:requestUrl,
type:'GET',
data:{pager:pager}, //把请求的页码告诉后台
dataType:'JSON',
success:function (result) {
initGlobalData(result.global_dict);
initHeader(result.table_config);
initBody(result.table_config,result.data_list);
initPager(result.pager);
}
})
}
//初始化分页
function initPager(pager) {
$('#idPagination').html(pager);
}
//初始化表头生成<tr><th>ID</th></tr>
var tr = document.createElement('tr');
function initHeader(table_config) {
$('#table_th').empty(); ////先清空所有的tr,再添加tr
$.each(table_config,function (k,item) {
//k是列表索引,item是字典
if(item.display){
th = document.createElement('th');
th.innerHTML=item.title;
$(tr).append(th);
}
});
console.log(tr);
$('#table_th').append(tr);
}
//初始化tbody内容
function initBody(table_config,data_list) {
$('#table_tb').empty(); //先清空,再添加
$.each(data_list,function (k,row) {
//row={'id': 1, 'cabinet_num': '12B', 'cabinet_order': '1'}
var tr = document.createElement('tr');
tr.setAttribute('row-id',row['id']); //生成tr标签时,就把行ID传给它,日后更新时根据这个ID更新
$.each(table_config,function (i,colConfig) {
/*{
'q': 'cabinet_num',
'title': '机柜号',
'display': True,
'text': {'content':'{n}-{m}','kwargs':{'n':'机柜','m':'@xx'}},
'sttrs': {'edit-enable': 'true', 'edit-type': 'select'}
}*/
if(colConfig.display){
var td = document.createElement('td');
//table_config.text={'content': '{n}-{m}', 'kwargs': {'n': '机柜', 'm': '@xx'}},
//colConfig.q是数据库中的字段名
//生成td的文本信息
var kwargs = {};
$.each(colConfig.text.kwargs,function (key,value) {
if(value.substring(0,2) == '@@'){
//两个@@开头的,把选项ID转换成内容
var globalName = value.substring(2,value.length);//全局变量的名称
var currentId = row[colConfig.q]; //获取的数据库中存储的数字类型值
var t = getText(globalName,currentId); //根据ID去全局变量中找对应内容
kwargs[key] = t;
}else if(value[0]=='@'){
//以@开头的就只取@后面的字段的值
kwargs[key] = row[value.substring(1,value.length)];
}else {
kwargs[key] = value;
}
});
var temp = colConfig.text.content.format(kwargs);
td.innerHTML = temp;
//设置td的属性colConfig.attrs = {'origin':'@status_id','edit-enable': 'true', 'edit-type': 'select'},
$.each(colConfig.attrs,function (kk,vv) {
if(vv[0] == '@'){ //vv=@status_id
td.setAttribute(kk,row[vv.substring(1,vv.length)]);//origin=1
}else{
td.setAttribute(kk,vv);
}
});
tr.append(td);
}
});
$('#table_tb').append(tr);
});
}
//设置全局变量,初始化下拉框里的选择项
function initGlobalData(global_dict) {
$.each(global_dict,function (k,v) {
//设置全局变量
window[k] = v;
})
}
//根据ID获取全局变量里对应内容
var ret = null;
function getText(globalName,currentId) {
//globalName='asset_type_choices'
//currentId=1
$.each(window[globalName],function (k,item) {
if(currentId == item[0]){
ret = item[1];
return
}
});
return ret;
}
//扩展方法
jQuery.extend({
'NB':function (url) {
requestUrl = url;
init();
bindEditMode();
bindCheckbox();
bindCheckAll();
bindCancelAll();
bindReverseAll();
bindSave();
bindChangePager();
},
'changePager':function (num) {
init(num);
}
});
})();
公共的JS组件-告别CURD的更多相关文章
- JS组件系列——BootstrapTable+KnockoutJS实现增删改查解决方案(三):两个Viewmodel搞定增删改查
前言:之前博主分享过knockoutJS和BootstrapTable的一些基础用法,都是写基础应用,根本谈不上封装,仅仅是避免了html控件的取值和赋值,远远没有将MVVM的精妙展现出来.最近项目打 ...
- vue.js组件化开发实践
前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了下面的内容.借油开车. 组件化 需求一到,接就是怎么实现,技术选型自然 ...
- JS组件系列——封装自己的JS组件,你也可以
前言:之前分享了那么多bootstrap组件的使用经验,这篇博主打算研究下JS组件的扩展和封装,我们来感受下JQuery为我们提供$.Extend的神奇,看看我们怎么自定义自己的组件,比如我们想扩展一 ...
- JS组件系列——封装自己的JS组件
前言:之前分享了那么多bootstrap组件的使用经验,这篇博主打算研究下JS组件的扩展和封装,我们来感受下JQuery为我们提供$.Extend的神奇,看看我们怎么自定义自己的组件,比如我们想扩展一 ...
- VUE.JS组件化
VUE.JS组件化 前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了下面的内容.借油开车. 组件化 需求一到,接就是怎 ...
- JS组件系列——BootstrapTable+KnockoutJS实现增删改查解决方案(一)
前言:出于某种原因,需要学习下Knockout.js,这个组件很早前听说过,但一直没尝试使用,这两天学习了下,觉得它真心不错,双向绑定的机制简直太爽了.今天打算结合bootstrapTable和Kno ...
- JS组件系列——BootstrapTable 行内编辑解决方案:x-editable
前言:之前介绍bootstrapTable组件的时候有提到它的行内编辑功能,只不过为了展示功能,将此一笔带过了,罪过罪过!最近项目里面还是打算将行内编辑用起来,于是再次研究了下x-editable组件 ...
- JS组件系列——BootstrapTable+KnockoutJS实现增删改查解决方案(四):自定义T4模板快速生成页面
前言:上篇介绍了下ko增删改查的封装,确实节省了大量的js代码.博主是一个喜欢偷懒的人,总觉得这些基础的增删改查效果能不能通过一个什么工具直接生成页面效果,啥代码都不用写了,那该多爽.于是研究了下T4 ...
- JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐(二)
前言:上篇 JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐 分享了几个项目中比较常用的组件,引起了许多园友的关注.这篇还是继续,因为博主觉得还有几个非常简单.实用的组件,实在不愿自己 ...
随机推荐
- Python获取文件夹的名字
dir = "../data/20170308/221.176.64.146/" # root 文件夹下的所有文件夹(包括子文件夹)的路径名字../data/20170308/22 ...
- 干货 | Java8 新特性教程
本教程翻译整理自 https://github.com/winterbe/java8-tutorial 本教程首发自个人网站: https://www.exception.site/java8/jav ...
- 死磕 java集合之TreeMap源码分析(二)- 内含红黑树分析全过程
欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. 插入元素 插入元素,如果元素在树中存在,则替换value:如果元素不存在,则插入到对应的位置, ...
- Carousel轮播图
<div id="carousel-example-generic" class="carousel slide" data-ride="ca ...
- MongoDB exception:connection failed
根据http://www.runoob.com/mongodb/mongodb-window-install.html的教程配置了MongoDB,Mongod.exe配置为 --port 指令表明mo ...
- Android--Task和BackStack高级
前言 之前的博客讲到了Android下Activity的启动模式,涉及到了Task和BackStack的内容,对这些不熟悉的朋友,可以先去看看:Android--Activity的启动模式.这篇博客主 ...
- 基于spark实现并行化Apriori算法
详细代码我已上传到github:click me 一. 实验要求 在 Spark2.3 平台上实现 Apriori 频繁项集挖掘的并行化算法.要求程序利用 Spark 进行并行计算. ...
- 环境与工具2:建立高效的mac环境
你的工作与生活离不开电脑,电脑是一个工具,也是一个环境.环境是不是绿水青山,是不是得心应手,这是很重要的事情.小程平时使用macbook来学习跟娱乐,最近重装了系统,很多环境与工具都需要重新组建. 那 ...
- leetcode — candy
/** * Source : https://oj.leetcode.com/problems/candy/ * * There are N children standing in a line. ...
- Oracle学习笔记二
多表查询: 笛卡尔积: 实际上是两张表的乘积,但是在实际开发中没有太大意义 格式: select * from 表1,表2 select * from emp; select * from dept; ...