Made gcode viewer capable of handling progress information
GCode viewer now updates its visualization (during printing) based on the current progress percentage, not based on the current line (which will not be available any more as part of the progress tuple with gcode streaming)
This commit is contained in:
parent
41aa633f38
commit
003109d59e
5 changed files with 242 additions and 88 deletions
|
|
@ -223,42 +223,31 @@
|
|||
var assumeNonDC = false;
|
||||
|
||||
for(var i=0;i<gcode.length;i++){
|
||||
// for(var len = gcode.length- 1, i=0;i!=len;i++){
|
||||
x=undefined;
|
||||
y=undefined;
|
||||
z=undefined;
|
||||
retract = 0;
|
||||
|
||||
var line = gcode[i].line;
|
||||
var percentage = gcode[i].percentage;
|
||||
|
||||
extrude=false;
|
||||
gcode[i] = gcode[i].split(/[\(;]/)[0];
|
||||
line = line.split(/[\(;]/)[0];
|
||||
|
||||
// prevRetract=0;
|
||||
// retract=0;
|
||||
// if(gcode[i].match(/^(?:G0|G1)\s+/i)){
|
||||
if(reg.test(gcode[i])){
|
||||
var args = gcode[i].split(/\s/);
|
||||
if(reg.test(line)){
|
||||
var args = line.split(/\s/);
|
||||
for(j=0;j<args.length;j++){
|
||||
// console.log(args);
|
||||
// if(!args[j])continue;
|
||||
switch(argChar = args[j].charAt(0).toLowerCase()){
|
||||
case 'x':
|
||||
x=args[j].slice(1);
|
||||
// if(x === prevX){
|
||||
// x=undefined;
|
||||
// }
|
||||
break;
|
||||
case 'y':
|
||||
y=args[j].slice(1);
|
||||
// if(y===prevY){
|
||||
// y=undefined;
|
||||
// }
|
||||
break;
|
||||
case 'z':
|
||||
z=args[j].slice(1);
|
||||
z = Number(z);
|
||||
if(z == prevZ)continue;
|
||||
// z = Number(z);
|
||||
if(z == prevZ) continue;
|
||||
if(z_heights.hasOwnProperty(z)){
|
||||
layer = z_heights[z];
|
||||
}else{
|
||||
|
|
@ -267,9 +256,6 @@
|
|||
}
|
||||
sendLayer = layer;
|
||||
sendLayerZ = z;
|
||||
// if(parseFloat(prevZ) < )
|
||||
// if(args[j].charAt(1) === "-")layer--;
|
||||
// else layer++;
|
||||
prevZ = z;
|
||||
break;
|
||||
case 'e':
|
||||
|
|
@ -292,13 +278,11 @@
|
|||
retract = -1;
|
||||
}
|
||||
else if(prev_extrude["abs"]==0){
|
||||
// if(prevRetract <0 )prevRetract=retract;
|
||||
retract = 0;
|
||||
}else if(prev_extrude["abs"]>0&&prevRetract < 0){
|
||||
prevRetract = 0;
|
||||
retract = 1;
|
||||
} else {
|
||||
// prevRetract = retract;
|
||||
retract = 0;
|
||||
}
|
||||
prev_extrude[argChar] = numSlice;
|
||||
|
|
@ -317,24 +301,24 @@
|
|||
prev_extrude["abs"] = Math.sqrt((prevX-x)*(prevX-x)+(prevY-y)*(prevY-y));
|
||||
}
|
||||
if(!model[layer])model[layer]=[];
|
||||
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined'||retract!=0) model[layer][model[layer].length] = {x: Number(x), y: Number(y), z: Number(z), extrude: extrude, retract: Number(retract), noMove: false, extrusion: (extrude||retract)?Number(prev_extrude["abs"]):0, prevX: Number(prevX), prevY: Number(prevY), prevZ: Number(prevZ), speed: Number(lastF), gcodeLine: Number(i)};
|
||||
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined'||retract!=0) model[layer][model[layer].length] = {x: Number(x), y: Number(y), z: Number(z), extrude: extrude, retract: Number(retract), noMove: false, extrusion: (extrude||retract)?Number(prev_extrude["abs"]):0, prevX: Number(prevX), prevY: Number(prevY), prevZ: Number(prevZ), speed: Number(lastF), gcodeLine: Number(i), percentage: percentage};
|
||||
//{x: x, y: y, z: z, extrude: extrude, retract: retract, noMove: false, extrusion: (extrude||retract)?prev_extrude["abs"]:0, prevX: prevX, prevY: prevY, prevZ: prevZ, speed: lastF, gcodeLine: i};
|
||||
if(typeof(x) !== 'undefined') prevX = x;
|
||||
if(typeof(y) !== 'undefined') prevY = y;
|
||||
} else if(gcode[i].match(/^(?:M82)/i)){
|
||||
} else if(line.match(/^(?:M82)/i)){
|
||||
extrudeRelative = false;
|
||||
}else if(gcode[i].match(/^(?:G91)/i)){
|
||||
}else if(line.match(/^(?:G91)/i)){
|
||||
extrudeRelative=true;
|
||||
}else if(gcode[i].match(/^(?:G90)/i)){
|
||||
}else if(line.match(/^(?:G90)/i)){
|
||||
extrudeRelative=false;
|
||||
}else if(gcode[i].match(/^(?:M83)/i)){
|
||||
}else if(line.match(/^(?:M83)/i)){
|
||||
extrudeRelative=true;
|
||||
}else if(gcode[i].match(/^(?:M101)/i)){
|
||||
}else if(line.match(/^(?:M101)/i)){
|
||||
dcExtrude=true;
|
||||
}else if(gcode[i].match(/^(?:M103)/i)){
|
||||
}else if(line.match(/^(?:M103)/i)){
|
||||
dcExtrude=false;
|
||||
}else if(gcode[i].match(/^(?:G92)/i)){
|
||||
var args = gcode[i].split(/\s/);
|
||||
}else if(line.match(/^(?:G92)/i)){
|
||||
var args = line.split(/\s/);
|
||||
for(j=0;j<args.length;j++){
|
||||
switch(argChar = args[j].charAt(0).toLowerCase()){
|
||||
case 'x':
|
||||
|
|
@ -354,16 +338,15 @@
|
|||
else {
|
||||
prev_extrude[argChar] = numSlice;
|
||||
}
|
||||
// prevZ = z;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!model[layer])model[layer]=[];
|
||||
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined') model[layer][model[layer].length] = {x: parseFloat(x), y: parseFloat(y), z: parseFloat(z), extrude: extrude, retract: parseFloat(retract), noMove: true, extrusion: (extrude||retract)?parseFloat(prev_extrude["abs"]):0, prevX: parseFloat(prevX), prevY: parseFloat(prevY), prevZ: parseFloat(prevZ), speed: parseFloat(lastF),gcodeLine: parseFloat(i)};
|
||||
}else if(gcode[i].match(/^(?:G28)/i)){
|
||||
var args = gcode[i].split(/\s/);
|
||||
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined') model[layer][model[layer].length] = {x: parseFloat(x), y: parseFloat(y), z: parseFloat(z), extrude: extrude, retract: parseFloat(retract), noMove: true, extrusion: (extrude||retract)?parseFloat(prev_extrude["abs"]):0, prevX: parseFloat(prevX), prevY: parseFloat(prevY), prevZ: parseFloat(prevZ), speed: parseFloat(lastF),gcodeLine: parseFloat(i), percentage: percentage};
|
||||
}else if(line.match(/^(?:G28)/i)){
|
||||
var args = line.split(/\s/);
|
||||
for(j=0;j<args.length;j++){
|
||||
switch(argChar = args[j].charAt(0).toLowerCase()){
|
||||
case 'x':
|
||||
|
|
@ -405,17 +388,11 @@
|
|||
}
|
||||
prevZ = z;
|
||||
}
|
||||
// x=0, y=0,z=0,prevZ=0, extrude=false;
|
||||
// if(typeof(prevX) === 'undefined'){prevX=0;}
|
||||
// if(typeof(prevY) === 'undefined'){prevY=0;}
|
||||
|
||||
if(!model[layer])model[layer]=[];
|
||||
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined'||retract!=0) model[layer][model[layer].length] = {x: Number(x), y: Number(y), z: Number(z), extrude: extrude, retract: Number(retract), noMove: false, extrusion: (extrude||retract)?Number(prev_extrude["abs"]):0, prevX: Number(prevX), prevY: Number(prevY), prevZ: Number(prevZ), speed: Number(lastF), gcodeLine: Number(i)};
|
||||
// if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined') model[layer][model[layer].length] = {x: x, y: y, z: z, extrude: extrude, retract: retract, noMove:false, extrusion: (extrude||retract)?prev_extrude["abs"]:0, prevX: prevX, prevY: prevY, prevZ: prevZ, speed: lastF, gcodeLine: parseFloat(i)};
|
||||
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined'||retract!=0) model[layer][model[layer].length] = {x: Number(x), y: Number(y), z: Number(z), extrude: extrude, retract: Number(retract), noMove: false, extrusion: (extrude||retract)?Number(prev_extrude["abs"]):0, prevX: Number(prevX), prevY: Number(prevY), prevZ: Number(prevZ), speed: Number(lastF), gcodeLine: Number(i), percentage: percentage};
|
||||
}
|
||||
if(typeof(sendLayer) !== "undefined"){
|
||||
// sendLayerToParent(sendLayer, sendLayerZ, i/gcode.length*100);
|
||||
// sendLayer = undefined;
|
||||
|
||||
if(i-lastSend > gcode.length*0.02 && sendMultiLayer.length != 0){
|
||||
lastSend = i;
|
||||
|
|
@ -429,13 +406,7 @@
|
|||
sendLayerZ = undefined;
|
||||
}
|
||||
}
|
||||
// sendMultiLayer[sendMultiLayer.length] = layer;
|
||||
// sendMultiLayerZ[sendMultiLayerZ.length] = z;
|
||||
sendMultiLayerToParent(sendMultiLayer, sendMultiLayerZ, i/gcode.length*100);
|
||||
|
||||
// if(gCodeOptions["sortLayers"])sortLayers();
|
||||
// if(gCodeOptions["purgeEmptyLayers"])purgeLayers();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -23,57 +23,73 @@ GCODE.gCodeReader = (function(){
|
|||
purgeEmptyLayers: true,
|
||||
analyzeModel: false
|
||||
};
|
||||
var linesCmdIndex = {};
|
||||
|
||||
var prepareGCode = function(){
|
||||
var percentageTree = undefined;
|
||||
|
||||
var prepareGCode = function(totalSize){
|
||||
if(!lines)return;
|
||||
gcode = [];
|
||||
var i, tmp;
|
||||
var i, tmp, byteCount;
|
||||
|
||||
byteCount = 0;
|
||||
for(i=0;i<lines.length;i++){
|
||||
// if(lines[i].match(/^(G0|G1|G90|G91|G92|M82|M83|G28)/i))gcode.push(lines[i]);
|
||||
byteCount += lines[i].length + 1; // line length + \n
|
||||
tmp = lines[i].indexOf(";");
|
||||
if(tmp > 1 || tmp === -1) {
|
||||
gcode.push(lines[i]);
|
||||
gcode.push({line: lines[i], percentage: byteCount * 100 / totalSize});
|
||||
}
|
||||
}
|
||||
lines = [];
|
||||
// console.log("GCode prepared");
|
||||
};
|
||||
|
||||
var sortLayers = function(){
|
||||
var sortedZ = [];
|
||||
var tmpModel = [];
|
||||
// var cnt = 0;
|
||||
// console.log(z_heights);
|
||||
|
||||
for(var layer in z_heights){
|
||||
sortedZ[z_heights[layer]] = layer;
|
||||
// cnt++;
|
||||
}
|
||||
// console.log("cnt is " + cnt);
|
||||
|
||||
sortedZ.sort(function(a,b){
|
||||
return a-b;
|
||||
});
|
||||
// console.log(sortedZ);
|
||||
// console.log(model.length);
|
||||
|
||||
for(var i=0;i<sortedZ.length;i++){
|
||||
// console.log("i is " + i +" and sortedZ[i] is " + sortedZ[i] + "and z_heights[] is " + z_heights[sortedZ[i]] );
|
||||
if(typeof(z_heights[sortedZ[i]]) === 'undefined')continue;
|
||||
tmpModel[i] = model[z_heights[sortedZ[i]]];
|
||||
}
|
||||
model = tmpModel;
|
||||
// console.log(model.length);
|
||||
delete tmpModel;
|
||||
};
|
||||
|
||||
var prepareLinesIndex = function(){
|
||||
linesCmdIndex = {};
|
||||
percentageTree = undefined;
|
||||
|
||||
for (var l in model){
|
||||
for (var i=0; i< model[l].length; i++){
|
||||
linesCmdIndex[model[l][i].gcodeLine] = {layer: l, cmd: i};
|
||||
for (var l in model) {
|
||||
for (var i=0; i< model[l].length; i++) {
|
||||
var percentage = model[l][i].percentage;
|
||||
var value = {layer: l, cmd: i};
|
||||
if (!percentageTree) {
|
||||
percentageTree = new AVLTree({key: percentage, value: value}, "key");
|
||||
} else {
|
||||
percentageTree.add({key: percentage, value: value});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var searchInPercentageTree = function(key) {
|
||||
if (percentageTree === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var elements = percentageTree.findBest(key);
|
||||
if (elements.length == 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return elements[0];
|
||||
};
|
||||
|
||||
var purgeLayers = function(){
|
||||
var purge=true;
|
||||
|
|
@ -102,13 +118,13 @@ GCODE.gCodeReader = (function(){
|
|||
return {
|
||||
|
||||
loadFile: function(reader){
|
||||
// console.log("loadFile");
|
||||
model = [];
|
||||
z_heights = [];
|
||||
|
||||
var totalSize = reader.target.result.length;
|
||||
lines = reader.target.result.split(/\n/);
|
||||
reader.target.result = null;
|
||||
prepareGCode();
|
||||
prepareGCode(totalSize);
|
||||
|
||||
worker.postMessage({
|
||||
"cmd":"parseGCode",
|
||||
|
|
@ -129,32 +145,21 @@ GCODE.gCodeReader = (function(){
|
|||
}
|
||||
},
|
||||
passDataToRenderer: function(){
|
||||
// console.log(model);
|
||||
if(gCodeOptions["sortLayers"])sortLayers();
|
||||
// console.log(model);
|
||||
if(gCodeOptions["purgeEmptyLayers"])purgeLayers();
|
||||
prepareLinesIndex();
|
||||
// console.log(model);
|
||||
GCODE.renderer.doRender(model, 0);
|
||||
// GCODE.renderer3d.setModel(model);
|
||||
|
||||
},
|
||||
processLayerFromWorker: function(msg){
|
||||
// var cmds = msg.cmds;
|
||||
// var layerNum = msg.layerNum;
|
||||
// var zHeightObject = msg.zHeightObject;
|
||||
// var isEmpty = msg.isEmpty;
|
||||
// console.log(zHeightObject);
|
||||
model[msg.layerNum] = msg.cmds;
|
||||
z_heights[msg.zHeightObject.zValue] = msg.zHeightObject.layer;
|
||||
// GCODE.renderer.doRender(model, msg.layerNum);
|
||||
},
|
||||
processMultiLayerFromWorker: function(msg){
|
||||
for(var i=0;i<msg.layerNum.length;i++){
|
||||
model[msg.layerNum[i]] = msg.model[msg.layerNum[i]];
|
||||
z_heights[msg.zHeightObject.zValue[i]] = msg.layerNum[i];
|
||||
}
|
||||
// console.log(model);
|
||||
},
|
||||
processAnalyzeModelDone: function(msg){
|
||||
min = msg.min;
|
||||
|
|
@ -190,8 +195,13 @@ GCODE.gCodeReader = (function(){
|
|||
var result = {first: model[layer][fromSegments].gcodeLine, last: model[layer][toSegments].gcodeLine};
|
||||
return result;
|
||||
},
|
||||
getLinesCmdIndex: function(line){
|
||||
return linesCmdIndex[line];
|
||||
getCmdIndexForPercentage: function(percentage) {
|
||||
var command = searchInPercentageTree(percentage);
|
||||
if (command === undefined) {
|
||||
return undefined
|
||||
} else {
|
||||
return command.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}());
|
||||
|
|
|
|||
169
octoprint/static/js/avltree.js
Normal file
169
octoprint/static/js/avltree.js
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
// AVLTree ///////////////////////////////////////////////////////////////////
|
||||
// self file is originally from the Concentré XML project (version 0.2.1)
|
||||
// Licensed under GPL and LGPL
|
||||
//
|
||||
// Modified by Jeremy Stephens.
|
||||
//
|
||||
// Taken from: https://gist.github.com/viking/2424106, modified to not only use string literals when searching
|
||||
|
||||
// Pass in the attribute you want to use for comparing
|
||||
function AVLTree(n, attr) {
|
||||
var self = this;
|
||||
|
||||
self.attr = attr;
|
||||
self.left = null;
|
||||
self.right = null;
|
||||
self.node = n;
|
||||
self.depth = 1;
|
||||
self.elements = [n];
|
||||
|
||||
self.balance = function() {
|
||||
var ldepth = self.left == null ? 0 : self.left.depth;
|
||||
var rdepth = self.right == null ? 0 : self.right.depth;
|
||||
|
||||
if (ldepth > rdepth + 1) {
|
||||
// LR or LL rotation
|
||||
var lldepth = self.left.left == null ? 0 : self.left.left.depth;
|
||||
var lrdepth = self.left.right == null ? 0 : self.left.right.depth;
|
||||
|
||||
if (lldepth < lrdepth) {
|
||||
// LR rotation consists of a RR rotation of the left child
|
||||
self.left.rotateRR();
|
||||
// plus a LL rotation of self node, which happens anyway
|
||||
}
|
||||
self.rotateLL();
|
||||
} else if (ldepth + 1 < rdepth) {
|
||||
// RR or RL rorarion
|
||||
var rrdepth = self.right.right == null ? 0 : self.right.right.depth;
|
||||
var rldepth = self.right.left == null ? 0 : self.right.left.depth;
|
||||
|
||||
if (rldepth > rrdepth) {
|
||||
// RR rotation consists of a LL rotation of the right child
|
||||
self.right.rotateLL();
|
||||
// plus a RR rotation of self node, which happens anyway
|
||||
}
|
||||
self.rotateRR();
|
||||
}
|
||||
}
|
||||
|
||||
self.rotateLL = function() {
|
||||
// the left side is too long => rotate from the left (_not_ leftwards)
|
||||
var nodeBefore = self.node;
|
||||
var elementsBefore = self.elements;
|
||||
var rightBefore = self.right;
|
||||
self.node = self.left.node;
|
||||
self.elements = self.left.elements;
|
||||
self.right = self.left;
|
||||
self.left = self.left.left;
|
||||
self.right.left = self.right.right;
|
||||
self.right.right = rightBefore;
|
||||
self.right.node = nodeBefore;
|
||||
self.right.elements = elementsBefore;
|
||||
self.right.updateInNewLocation();
|
||||
self.updateInNewLocation();
|
||||
}
|
||||
|
||||
self.rotateRR = function() {
|
||||
// the right side is too long => rotate from the right (_not_ rightwards)
|
||||
var nodeBefore = self.node;
|
||||
var elementsBefore = self.elements;
|
||||
var leftBefore = self.left;
|
||||
self.node = self.right.node;
|
||||
self.elements = self.right.elements;
|
||||
self.left = self.right;
|
||||
self.right = self.right.right;
|
||||
self.left.right = self.left.left;
|
||||
self.left.left = leftBefore;
|
||||
self.left.node = nodeBefore;
|
||||
self.left.elements = elementsBefore;
|
||||
self.left.updateInNewLocation();
|
||||
self.updateInNewLocation();
|
||||
}
|
||||
|
||||
self.updateInNewLocation = function() {
|
||||
self.getDepthFromChildren();
|
||||
}
|
||||
|
||||
self.getDepthFromChildren = function() {
|
||||
self.depth = self.node == null ? 0 : 1;
|
||||
if (self.left != null) {
|
||||
self.depth = self.left.depth + 1;
|
||||
}
|
||||
if (self.right != null && self.depth <= self.right.depth) {
|
||||
self.depth = self.right.depth + 1;
|
||||
}
|
||||
}
|
||||
|
||||
self.compare = function(n1, n2) {
|
||||
var v1 = n1[self.attr];
|
||||
var v2 = n2[self.attr];
|
||||
if (v1 == v2) {
|
||||
return 0;
|
||||
}
|
||||
if (v1 < v2) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
self.add = function(n) {
|
||||
var o = self.compare(n, self.node);
|
||||
if (o == 0) {
|
||||
self.elements.push(n);
|
||||
return false;
|
||||
}
|
||||
|
||||
var ret = false;
|
||||
if (o == -1) {
|
||||
if (self.left == null) {
|
||||
self.left = new AVLTree(n, self.attr);
|
||||
ret = true;
|
||||
} else {
|
||||
ret = self.left.add(n);
|
||||
if (ret) {
|
||||
self.balance();
|
||||
}
|
||||
}
|
||||
} else if (o == 1) {
|
||||
if (self.right == null) {
|
||||
self.right = new AVLTree(n, self.attr);
|
||||
ret = true;
|
||||
} else {
|
||||
ret = self.right.add(n);
|
||||
if (ret) {
|
||||
self.balance();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
self.getDepthFromChildren();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
self.findBest = function(value) {
|
||||
if (value < self.node[self.attr]) {
|
||||
if (self.left != null) {
|
||||
return self.left.findBest(value);
|
||||
}
|
||||
} else if (value > self.node[self.attr]) {
|
||||
if (self.right != null) {
|
||||
return self.right.findBest(value);
|
||||
}
|
||||
}
|
||||
|
||||
return self.elements;
|
||||
}
|
||||
|
||||
self.find = function(value) {
|
||||
var elements = self.findBest(value);
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
if (elements[i][self.attr] == value) {
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1093,13 +1093,16 @@ function GcodeViewModel(loginStateViewModel) {
|
|||
}
|
||||
|
||||
self._processData = function(data) {
|
||||
if(!self.enabled)return;
|
||||
if (!self.enabled) return;
|
||||
if (!data.job.filename) return;
|
||||
|
||||
if(self.loadedFilename == data.job.filename) {
|
||||
var cmdIndex = GCODE.gCodeReader.getLinesCmdIndex(data.progress.progress);
|
||||
if(cmdIndex){
|
||||
GCODE.renderer.render(cmdIndex.layer, 0, cmdIndex.cmd);
|
||||
GCODE.ui.updateLayerInfo(cmdIndex.layer);
|
||||
if(self.loadedFilename && self.loadedFilename == data.job.filename) {
|
||||
if (data.state.flags && (data.state.flags.printing || data.state.flags.paused)) {
|
||||
var cmdIndex = GCODE.gCodeReader.getCmdIndexForPercentage(data.progress.progress * 100);
|
||||
if(cmdIndex){
|
||||
GCODE.renderer.render(cmdIndex.layer, 0, cmdIndex.cmd);
|
||||
GCODE.ui.updateLayerInfo(cmdIndex.layer);
|
||||
}
|
||||
}
|
||||
self.errorCount = 0
|
||||
} else if (data.job.filename) {
|
||||
|
|
|
|||
|
|
@ -579,6 +579,7 @@
|
|||
<script type="text/javascript" src="{{ url_for('static', filename='js/modernizr.custom.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ url_for('static', filename='js/underscore.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ url_for('static', filename='js/knockout.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ url_for('static', filename='js/avltree.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ url_for('static', filename='js/bootstrap/bootstrap.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ url_for('static', filename='js/bootstrap/bootstrap-modalmanager.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ url_for('static', filename='js/bootstrap/bootstrap-modal.js') }}"></script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue