关键前端代码注释
前端代码文档
按照文件进行罗列,我只标注我认为重要的函数了,剩下的大部分都是相对简单的
1、canvas.html
//定义jsplumb的连线样式
var my_end_point = {
endpoint: ["Dot", {radius: 5}],
connectorStyle: {
stroke: "#fc2f49",
strokeWidth: 3,
},
isSource: true,
isTarget: true,
maxConnections: -1, //不限制连线数量
connector: ["Flowchart", {stub: [40, 60], gap: 5, cornerRadius: 5, alwaysRespectStubs: true}],
connectorOverlays: [["Arrow", {width: 10, length: 10, location: 1}]],
connectionsDetachable: true, //再次拖动让连线断开
};
//这个#是id选择器,html中的id是view_layer的,每次拖动时clone一个新的节点,这个被clone的拖动
//scope是指可被拖动的范围
//draggable使得这个元素可被拖动
$("#view_layer").draggable(
{
helper: "clone",
scope: "ss",
}
);
//canvas就是画布,盛放所有节点的地方
$("#canvas").droppable({
scope: "ss",//有相同值的draggable会被droppable接受,看上面的scope
//drop方法就是你拖动元素,鼠标放下的瞬间执行的函数
drop: function (event, ui) {
var left = parseInt(ui.offset.left - $("#canvas").offset().left);
var top = parseInt(ui.offset.top - $("#canvas").offset().top);
var name = ui.draggable[0].id;
canvas_cnt++;
var id = "canvas_" + canvas_cnt;
if (ui.hasOwnProperty('id')) {
id = ui['id'];
}
//这部分是添加一个元素,就是拖动的单个元素
$("#canvas").append("<div class='" + $("#" + name).attr("class") + "' id='" + id + "' name='" + name + "' type='" + $("#" + name).attr("type") + "' " +
" data-container='" + $("#" + name).attr("data-container") + "' data-toggle='" + $("#" + name).attr("data-toggle") + "' " + ">" + ui.draggable[0].innerHTML + "</div>");
$("#" + id).css("left", left).css("top", top);
//弹框可用这个是我自己加的,可以给每个被点击的元素加个弹框
// $("#" + id).popover(
// {
// trigger:'click', //触发方式
// title:"标题1",//设置 弹出框 的标题
// html: true, // 为true的话,data-content里就能放html代码了
// content:"<h1>111</h1>",//这里可以直接写字符串,也可以 是一个函数,该函数返回一个字符串;
// }
// );
//给被拖动的元素添加4个点上下左右
jsPlumb.draggable(id);
$("#" + id).draggable({containment: "parent"});
jsPlumb.addEndpoint(id, {anchor: 'Top'}, my_end_point);
jsPlumb.addEndpoint(id, {anchor: 'Left'}, my_end_point);
jsPlumb.addEndpoint(id, {anchor: 'Right'}, my_end_point);
jsPlumb.addEndpoint(id, {anchor: 'Bottom'}, my_end_point);
/*doubleclick("#" + id);*/
/*$("#" + id).on("click", function () {
if (confirm("确定要删除吗?")) {
jsPlumb.removeAllEndpoints($(this).attr("id"));
$(this).remove();
}
});*/
//把元素存到session里
if (name == "start") {
window.sessionStorage.setItem(id, "{\"start\":\"true\"}");
}
if (name == "element_wise_add_layer") {
window.sessionStorage.setItem(id, "{\"element_wise_add_layer\":\"true\"}");
}
if (name == "view_layer") {
window.sessionStorage.setItem(id, "{\"shape\":\"1\"}");
}
if (name == "concatenate_layer") {
window.sessionStorage.setItem(id, "{\"dim\":\"1\"}");
}
if (name == "linear_layer") {
window.sessionStorage.setItem(id, "{\"in_channels\":\"1\",\"out_channels\":\"1\"}");
}
if (name == "conv1d_layer") {
window.sessionStorage.setItem(id, "{\"in_channels\":\"1\",\"out_channels\":\"1\",\"kernel_size\":\"1\",\"stride\":\"1\",\"padding\":\"0\",\"activity\":\"None\",\"pool_way\":\"None\",\"pool_kernel_size\":\"\",\"pool_stride\":\"\",\"pool_padding\":\"0\"}");
}
if (name == "conv2d_layer") {
window.sessionStorage.setItem(id, "{\"in_channels\":\"1\",\"out_channels\":\"1\",\"kernel_size\":\"1\",\"stride\":\"1\",\"padding\":\"0\",\"activity\":\"None\",\"pool_way\":\"None\",\"pool_kernel_size\":\"\",\"pool_stride\":\"\",\"pool_padding\":\"0\"}");
}
//把该元素的菜单内容绑定,取消默认行为
$("#" + id).bind("contextmenu", function () {
return false;
});
/*$("#" + id).mousedown(function (e) {
//右键为3
if (3 == e.which) {
if (confirm("确定要删除吗?")) {
jsPlumb.removeAllEndpoints($(this).attr("id"));
$(this).remove();
}
}
});*/
var has_move = false;
var has_down = false;
//绑定行为函数,鼠标点击,鼠标抬起,鼠标移开
//通过点选元素(不能拖动)替换活跃节点(画布右侧的操作是对活跃节点进行的)
$("#" + id).bind({
mousedown: function (e) {
has_move = false;
has_down = true;
return;
},
mousemove: function (e) {
has_move = true;
return;
},
mouseup: function (e) {
if (!has_move) {
if (window.sessionStorage.hasOwnProperty("active_node")) {
$("#" + window.sessionStorage.getItem("active_node")).removeClass("selected");
}
window.sessionStorage.setItem("active_node", id);
$("#" + id).addClass("selected");
show_form(id, name);
}
has_move = false;
has_down = false;
return;
}
});
/*var tmp_list = searh_layer[name].split("id_anchor");
var popover_content= tmp_list[0]+"popover_"+id+tmp_list[1];*/
}
});
//页面加载完毕后执行的函数
$(document).ready(function () {
//根据解析页面传参
var query_object = getQueryObject(window.location.href);
if (query_object.hasOwnProperty("id")) {
var net_id = query_object["id"];
//发送异步请求
$.ajax({
type: 'GET',
url: 'api/NeuralNetwork/network/' + net_id + '/',
beforeSend: function (XMLHttpRequest) {
//这个是认证的token,取出token到session
var token = window.sessionStorage.getItem('token');
if (token != null) {
XMLHttpRequest.setRequestHeader("Authorization", "JWT " + token);
}
},
//返回状态码为200时执行的函数
success: function (net_work) {
var structure = eval('(' + net_work["structure"] + ')');
var nets = structure['nets'];
var nets_conn = structure['nets_conn'];
var static_val = structure['static'];
var drop_function = $("#canvas").droppable('option', 'drop');
var event;
jQuery.each(nets, function (id, val) {
jsPlumb.ready(function () {
var ui = {
'offset': {
'left': parseInt(val['left'].split('px')) + $("#canvas").offset().left,
'top': parseInt(val['top'].split('px')) + $("#canvas").offset().top
},
'draggable': [{
"id": val['name'],
"innerHTML": $("#" + val['name'])[0].innerHTML
}],
'id': id
};
drop_function(event, ui);
});
window.sessionStorage.setItem(id, JSON.stringify(val['attribute']));
});
jQuery.each(nets_conn, function (id, val) {
jsPlumb.ready(function () {
jsPlumb.connect({
"source": val['source']['id'],
"target": val['target']['id'],
"anchors": [val['source']['anchor_position'], val['target']['anchor_position']],
"endpoint": ["Dot", {radius: 5}],
"paintStyle": {
stroke: "#fc2f49",
strokeWidth: 3,
},
"maxConnections": -1,
"connector": ["Flowchart", {
stub: [40, 60],
gap: 5,
cornerRadius: 5,
alwaysRespectStubs: true
}],
"overlays": [["Arrow", {width: 10, length: 10, location: 1}]],
"connectionsDetachable": true,
})
});
});
$("#epoch").val(static_val['epoch']);
$("#optimzier").find("[value = \"" + static_val['optimizer'] + "\"]").attr("selected", "selected");
$('#learning_rate').val(static_val['learning_rate']);
$('#batch_size').val(static_val['batch_size'])
}
});
}
//这里是统计访问次数的
$.ajax({
type: 'POST',
data: "{\"name\":\"index\"}",
url: 'api/journal/visit/',
contentType: 'application/json; charset=UTF-8',
beforeSend: function (XMLHttpRequest) {
var token = window.sessionStorage.getItem('token');
if (token != null) {
XMLHttpRequest.setRequestHeader("Authorization", "JWT " + token)
}
},
})
});
//这个函数是用来执行,点击后右侧弹出的那个参数栏
function show_form(id, name) {
//先清除之前的参数栏
$("#parameters").children().remove();
if(no_popover.includes(name)){
$("#parameters").append("<a href='javascript:void(0);' onclick='delete_layer(\"" + id + "\")' class='button button-caution button-rounded'>删除该模块</a>");
return;
}
$("#parameters").append(get_content(name, id));
$("#parameters").append("<a href='javascript:void(0);' onclick='delete_layer(\"" + id + "\")' class='button button-caution button-rounded'>删除该模块</a>");
if (name == "conv1d_layer") {
var data = eval('(' + window.sessionStorage.getItem(id) + ')');
$("#" + id + "activity").find("[value = \"" + data["activity"] + "\"]").attr("selected", "selected");
$("#" + id + "pool_way").find("[value = \"" + data["pool_way"] + "\"]").attr("selected", "selected");
}
if (name == "conv2d_layer") {
var data = eval('(' + window.sessionStorage.getItem(id) + ')');
$("#" + id + "activity").find("[value = \"" + data["activity"] + "\"]").attr("selected", "selected");
$("#" + id + "pool_way").find("[value = \"" + data["pool_way"] + "\"]").attr("selected", "selected");
}
$("[name='pool_way']").bind('change', function () {
if ($(this).val() == 'None') {
$(this).parent().parent().find("[name='pool_kernel_size']").attr("disabled", true);
$(this).parent().parent().find("[name='pool_stride']").attr("disabled", true);
$(this).parent().parent().find("[name='pool_padding']").attr("disabled", true);
}
else {
$(this).parent().parent().find("[name='pool_kernel_size']").removeAttr("disabled");
$(this).parent().parent().find("[name='pool_stride']").removeAttr("disabled");
$(this).parent().parent().find("[name='pool_padding']").removeAttr("disabled");
}
});
$("#parameters").find("input,select").change(function () {
switch ($("#form" + id).attr("name")) {
case "view_layer":
save_attr_view_layer_form(id);
break;
case "concatenate_layer":
save_attr_concatenate_layer_form(id);
break;
case "linear_layer":
save_attr_linear_layer_form(id);
break;
case "conv1d_layer":
save_attr_conv1d_layer_form(id);
break;
case "conv2d_layer":
save_attr_conv2d_layer_from(id);
break;
default:
return;
}
})
}
2、base_service.js
//这个函数是用来解析url后面的参数的
function getQueryObject(url) {
url = url == null ? window.location.href : url;
var search = url.substring(url.lastIndexOf("?") + 1);
var obj = {};
//一个经典漂亮的正则表达式,用来解析url后面参数
var reg = /([^?&=]+)=([^?&=]*)/g;
search.replace(reg, function (rs, $1, $2) {
var name = decodeURIComponent($1);
var val = decodeURIComponent($2);
val = String(val);
obj[name] = val;
return rs;
});
//返回的是url后面的参数字典
return obj;
}
//登陆请求
function login() {
var username = $("#username_log").val();
var password = $("#pwd_log").val();
var data = {
"username": username,
"password": password
};
$.ajax({
type: 'POST',
url: 'api/user/login/',
async:false,//note:这里ajax必须为同步请求,两个ajax必须先拿token,再拿用户信息
data: JSON.stringify(data),
contentType: 'application/json; charset=UTF-8',
success: function (data_return) {
var token = data_return["token"];
window.sessionStorage.setItem('token', token)
},
error: function (data_return) {
alert("账号密码错误,请重新登录");
console.log(data_return["responseText"])
}
});
$.ajax({
type: 'GET',
async:false,
url: 'api/user/info/',
beforeSend: function (XMLHttpRequest) {
var token = window.sessionStorage.getItem('token');
if (token != null) {
XMLHttpRequest.setRequestHeader("Authorization", "JWT " + token)
}
},
success: function (data_return) {
window.sessionStorage.setItem('userinfo', JSON.stringify(data_return));
window.location.href = "canvas.html"
}
});
}
//注册请求
function register() {
//todo:加正则判断
var username = $("#username_reg").val();
var password = $("#pwd_reg").val();
if ($('#pwd_confirm_reg').val() != password) {
alert("两次输入密码不一致");
return;
}
var email = $("#email_reg").val();
var data = {
"username": username,
"email": email,
"password": password
};
$.ajax({
type: 'POST',
url: 'api/user/register/',
data: JSON.stringify(data),
contentType: 'application/json; charset=UTF-8',
success: function (data_return) {
var token = data_return["token"];
window.sessionStorage.setItem('token', token);
window.sessionStorage.setItem('userinfo', JSON.stringify(data_return));
window.location.href = "canvas.html"
},
error: function (data_return) {
alert("用户名或邮箱已被注册")
console.log(data_return["responseText"])
}
})
}
//登出请求
function logout() {
window.sessionStorage.removeItem('token');
window.sessionStorage.removeItem('userinfo');
$("#user_nav").hide();
$("#login_nav").show();
alert("用户已登出")
}
3、layer_form.js和layer_popover.js
这两个文件就是写死了
layer_form.js是每次点击到哪个模块,就把那个模块的参数作为一个表单显示到旁边,具体代码就不展示了。
layer_popover.js是模块的右侧出现弹出块,在canvas_beta里使用,这里的删除方式是右键删除
具体用哪个看他引用的是哪个
4、graph_action.js
//全局变量,用在几个调用后端的html页面里,还是有点用的
var gobalConfig = {
"base_url": "http://127.0.0.1:8000/"
};
//得到网络,就是把一个个网络块解析成各种参数
function get_network() {
var conn_list;
var nets_conn = [];
var nets = {};
$("#canvas").find(".node").each(function (index, element) {
var id = $(element).attr('id');
nets[id] = {
"name": $(element).attr('name'),
"attribute": eval('(' + window.sessionStorage.getItem(id) + ')'),
"left": $(element).css('left'),
"top": $(element).css('top')
}
});
conn_list = jsPlumb.getAllConnections();
console.log(conn_list);
for (var i = 0; i < conn_list.length; i++) {
var source_id = conn_list[i]["sourceId"];
var target_id = conn_list[i]["targetId"];
var conn = {
"source": {
"id": source_id,
"anchor_position": conn_list[i]["endpoints"][0]["anchor"]["type"]
},
"target": {
"id": target_id,
"anchor_position": conn_list[i]["endpoints"][1]["anchor"]["type"]
}
};
nets_conn.push(conn);
}
var epoch = $("#epoch").val();
if (epoch == "") {
epoch = "1";
}
var learning_rate = $("#learning_rate").val();
if (learning_rate == "") {
learning_rate = "0.5";
}
var batch_size = $("#batch_size").val();
if (batch_size == "") {
batch_size = "1";
}
var static = {
"epoch": epoch,
"optimizer": $("#optimzier").find("option:selected").val(),
"learning_rate": learning_rate,
"batch_size": batch_size
};
var data = {
"name": $("#model_name").val(),
"structure": {
"nets": nets,
"nets_conn": nets_conn,
"static": static
}
};
return data;
}
//向后端传输每个模块
function translate_network() {
//这边调用了上一个函数
var data = get_network()["structure"];
console.log(data);
$.ajax({
type: 'POST',
url: 'api/NeuralNetwork/getcode/',
data: JSON.stringify(data),
contentType: 'application/json; charset=UTF-8',
beforeSend: function (XMLHttpRequest) {
var token = window.sessionStorage.getItem('token');
if (token != null) {
XMLHttpRequest.setRequestHeader("Authorization", "JWT " + token)
}
},
success: function (data_return, status, xhr) {
if (xhr.status == 200) {
var main = "";
var main_print = "";
var model = "";
var model_print = "";
var ops = "";
var ops_print = "";
for (var i = 0; i < data_return["Main"].length; i++) {
main = main + data_return["Main"][i] + "<br>";
main_print=main_print+data_return["Main"][i] + "\n";
}
for (var i = 0; i < data_return["Model"].length; i++) {
model = model + data_return["Model"][i] + "<br>";
model_print=model_print+data_return["Model"][i] + "\n";
}
for (var i = 0; i < data_return["Ops"].length; i++) {
ops = ops + data_return["Ops"][i] + "<br>";
ops_print=ops_print+data_return["Ops"][i] + "\n";
}
var code = {
"model": model,
"main": main,
"ops": ops
};
var code_print = {
"model": model_print,
"main": main_print,
"ops": ops_print
};
window.sessionStorage.setItem("code", JSON.stringify(data_return));
window.sessionStorage.setItem("code_print", JSON.stringify(code_print));
window.open("show_code.html");
//window.location.href="show_code.html";
}
else {
alert(JSON.stringify(data_return));
}
},
error: function (data_return) {
alert(data_return["responseText"])
}
});
}
//保存网络模型,但是他这里面的jwt我还没完全搞明白,
function save_network() {
$("#save_modal").modal('hide');
if (!window.sessionStorage.hasOwnProperty("userinfo")) {
jump_to_login();
return
}
var data = get_network();
console.log(data);
var query_object = getQueryObject(window.location.href);
if (query_object.hasOwnProperty("id")) {
var net_id = query_object["id"];
$.ajax({
type: 'PUT',
url: 'api/NeuralNetwork/network/' + net_id + '/',
data: JSON.stringify(data),
contentType: 'application/json; charset=UTF-8',
beforeSend: function (XMLHttpRequest) {
var token = window.sessionStorage.getItem('token');
if (token != null) {
XMLHttpRequest.setRequestHeader("Authorization", "JWT " + token)
}
},
success: function (data_return) {
},
error: function (data_return) {
alert(data_return["responseText"])
}
});
} else {
$.ajax({
type: 'POST',
url: 'api/NeuralNetwork/network/',
data: JSON.stringify(data),
contentType: 'application/json; charset=UTF-8',
beforeSend: function (XMLHttpRequest) {
var token = window.sessionStorage.getItem('token');
if (token != null) {
XMLHttpRequest.setRequestHeader("Authorization", "JWT " + token)
}
},
success: function (data_return) {
},
error: function (data_return) {
alert(data_return["responseText"])
}
});
}
}
重要的我都罗列了,后续的都是一些细节,需要在具体写的时候再精读
学习资料链接
jsplumb学习网站:jsplumb中文基础教程
jQuery UI学习网站:菜鸟教程-jQuery UI
echarts学习网站:echarts中文官网
(实际上项目目前还没用到echarts)