公共的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组件福利篇:几款好用的组件推荐 分享了几个项目中比较常用的组件,引起了许多园友的关注.这篇还是继续,因为博主觉得还有几个非常简单.实用的组件,实在不愿自己 ...
随机推荐
- ThinkPHP 数据库操作(五) : 存储过程、数据集、分布式数据库
存储过程 5.0支持存储过程,如果我们定义了一个数据库存储过程 sp_query ,可以使用下面的方式调用: $result = Db::query('call sp_query(8)'); 返回的是 ...
- MySQL查询昨天的数据
SELECT * FROM `表名` WHERE TO_DAYS(`时间字段名`) = TO_DAYS(NOW()) - 1; 需要前几天的话就在后面减几天.
- Python内置函数(65)——type
英文文档: class type(object) class type(name, bases, dict) With one argument, return the type of an obje ...
- 【转】msfvenom使用指南
msfvenom命令行选项如下: Options: -p, --payload <payload> 指定需要使用的payload(攻击荷载).如果需要使用自定义的payload,请使用'- ...
- 探索ASP.NET Core中的IStartupFilter
原文:Exploring IStartupFilter in ASP.NET Core 作者:Andrew Lock 译者:Lamond Lu 在本篇博客中,我将介绍一下IStartupFilter, ...
- redis 系列26 Cluster高可用 (1)
一.概述 Redis集群提供了分布式数据库方案,集群通过分片来进行数据共享,并提供复制和故障转移功能.在大数据量方面的高可用方案,cluster集群比Sentinel有优势.但Redis集群并不支持处 ...
- Solr 10 - SolrCloud集群模式简介 + 组成结构的说明
目录 1 什么是SolrCloud 2 SolrCloud的结构 2.1 物理结构 2.2 逻辑结构 2.2.1 Collection(集合) 2.2.2 Core(内核) 2.2.3 Shard(分 ...
- 使用mpvue开发小程序教程(六)
在上一章节中,我们列举了在Vue中能用但在mpvue中不能用或需要特别注意的特性,在实际开发前了解一下还是很有必要的,可以避免浪费找错误的时间. 如果你使用过原生的小程序框架,你一定经历过或思考过怎么 ...
- Chapter 5 Blood Type——14
"You're wrong." His voice was almost inaudible. “你错了.” 他的声音几乎听不见 He looked down, stealing ...
- leetcode — decode-ways
/** * Source : https://oj.leetcode.com/problems/decode-ways/ * * * A message containing letters from ...