diff --git a/P-face.png b/P-face.png
new file mode 100644
index 0000000..1adcb14
Binary files /dev/null and b/P-face.png differ
diff --git a/gcoder.py b/gcoder.py
index 79c95bc..3b981ee 100755
--- a/gcoder.py
+++ b/gcoder.py
@@ -16,6 +16,17 @@
import sys
import re
+import math
+
+def deltalen(a,b):
+ d = object()
+ d.x = b.x - a.x
+ d.y = b.y - a.y
+ d.z = b.z - a.z
+
+ return math.sqrt((d.x*d.x)+(d.y*d.y)+(d.z*d.z))
+
+
class Line(object):
def __init__(self,l):
@@ -29,6 +40,7 @@ class Line(object):
self.raw = l.upper().lstrip()
self.imperial = False
self.relative = False
+ self.relative_e = False
if ";" in self.raw:
self.raw = self.raw.split(";")[0]
@@ -77,53 +89,55 @@ class Line(object):
return ""
def _get_float(self,which):
- return float(self.regex.findall(self.raw.split(which)[1])[0])
-
+ try:
+ return float(self.regex.findall(self.raw.split(which)[1])[0])
+ except:
+ return None
def _parse_coordinates(self):
- if "X" in self.raw:
- self._x = self._get_float("X")
+ try:
+ if "X" in self.raw:
+ self._x = self._get_float("X")
+ except:
+ pass
+
+ try:
+ if "Y" in self.raw:
+ self._y = self._get_float("Y")
+ except:
+ pass
+
+ try:
+ if "Z" in self.raw:
+ self._z = self._get_float("Z")
+ except:
+ pass
+
+ try:
+ if "E" in self.raw:
+ self.e = self._get_float("E")
+ except:
+ pass
+
+ try:
+ if "F" in self.raw:
+ self.f = self._get_float("F")
+ except:
+ pass
- if "Y" in self.raw:
- self._y = self._get_float("Y")
-
- if "Z" in self.raw:
- self._z = self._get_float("Z")
-
- if "E" in self.raw:
- self.e = self._get_float("E")
-
- if "F" in self.raw:
- self.f = self._get_float("F")
-
def is_move(self):
- return "G1" in self.raw or "G0" in self.raw
+ return self.command() and ("G1" in self.raw or "G0" in self.raw)
+
+
+ def __str__(self):
+ return self.raw
+
+class Layer(object):
+ def __init__(self,lines):
+ self.lines = lines
+
-
-class GCode(object):
- def __init__(self,data):
- self.lines = [Line(i) for i in data]
- self._preprocess()
-
- def _preprocess(self):
- #checks for G20, G21, G90 and G91, sets imperial and relative flags
- imperial = False
- relative = False
- for line in self.lines:
- if line.command() == "G20":
- imperial = True
- elif line.command() == "G21":
- imperial = False
- elif line.command() == "G90":
- relative = False
- elif line.command() == "G91":
- relative = True
- elif line.is_move():
- line.imperial = imperial
- line.relative = relative
-
-
def measure(self):
xmin = 999999999
ymin = 999999999
@@ -132,7 +146,8 @@ class GCode(object):
ymax = -999999999
zmax = -999999999
relative = False
-
+ relative_e = False
+
current_x = 0
current_y = 0
current_z = 0
@@ -147,13 +162,13 @@ class GCode(object):
x = line.x
y = line.y
z = line.z
-
+
if line.relative:
x = current_x + (x or 0)
y = current_y + (y or 0)
z = current_z + (z or 0)
-
-
+
+
if x and line.e:
if x < xmin:
xmin = x
@@ -169,22 +184,137 @@ class GCode(object):
zmin = z
if z > zmax:
zmax = z
-
+
current_x = x or current_x
current_y = y or current_y
current_z = z or current_z
-
- self.xmin = xmin
- self.ymin = ymin
- self.zmin = zmin
- self.xmax = xmax
- self.ymax = ymax
- self.zmax = zmax
-
- self.width = xmax-xmin
- self.depth = ymax-ymin
- self.height = zmax-zmin
+
+ return ( (xmin,xmax),(ymin,ymax),(zmin,zmax) )
+
+class GCode(object):
+ def __init__(self,data):
+ self.lines = [Line(i) for i in data]
+ self._preprocess()
+ self._create_layers()
+
+ def _preprocess(self):
+ #checks for G20, G21, G90 and G91, sets imperial and relative flags
+ imperial = False
+ relative = False
+ relative_e = False
+ for line in self.lines:
+ if line.command() == "G20":
+ imperial = True
+ elif line.command() == "G21":
+ imperial = False
+ elif line.command() == "G90":
+ relative = False
+ relative_e = False
+ elif line.command() == "G91":
+ relative = True
+ relative_e = True
+ elif line.command() == "M82":
+ relative_e = False
+ elif line.command() == "M83":
+ relative_e = True
+ elif line.is_move():
+ line.imperial = imperial
+ line.relative = relative
+ line.relative_e = relative_e
+
+ def _create_layers(self):
+ self.layers = []
+
+ prev_z = None
+ cur_z = 0
+ cur_lines = []
+ layer_index = []
+
+ temp_layers = {}
+ for line in self.lines:
+ if line.command() == "G92" and line.z != None:
+ cur_z = line.z
+ elif line.is_move():
+ if line.z != None:
+ if line.relative:
+ cur_z += line.z
+ else:
+ cur_z = line.z
+
+ if cur_z != prev_z:
+ old_lines = temp_layers.pop(prev_z,[])
+ old_lines += cur_lines
+ temp_layers[prev_z] = old_lines
+
+ if not prev_z in layer_index:
+ layer_index.append(prev_z)
+
+ cur_lines = []
+
+ cur_lines.append(line)
+ prev_z = cur_z
+
+
+ old_lines = temp_layers.pop(prev_z,[])
+ old_lines += cur_lines
+ temp_layers[prev_z] = old_lines
+
+ if not prev_z in layer_index:
+ layer_index.append(prev_z)
+
+ layer_index.sort()
+
+ for idx in layer_index:
+ cur_lines = temp_layers[idx]
+ has_movement = False
+ for l in cur_lines:
+ if l.is_move() and l.e != None:
+ has_movement = True
+ break
+
+ if has_movement:
+ self.layers.append(Layer(cur_lines))
+
+
+ def num_layers(self):
+ return len(self.layers)
+
+
+ def measure(self):
+ xmin = 999999999
+ ymin = 999999999
+ zmin = 0
+ xmax = -999999999
+ ymax = -999999999
+ zmax = -999999999
+
+ for l in self.layers:
+ xd,yd,zd = l.measure()
+ if xd[0] < xmin:
+ xmin = xd[0]
+ if xd[1] > xmax:
+ xmax = xd[1]
+
+ if yd[0] < ymin:
+ ymin = yd[0]
+ if yd[1] > ymax:
+ ymax = yd[1]
+
+ if zd[0] < zmin:
+ zmin = zd[0]
+ if zd[1] > zmax:
+ zmax = zd[1]
+
+ self.xmin = xmin
+ self.xmax = xmax
+ self.ymin = ymin
+ self.ymax = ymax
+ self.zmin = zmin
+ self.zmax = zmax
+ self.width = xmax - xmin
+ self.depth = ymax - ymin
+ self.height = zmax - zmin
def filament_length(self):
total_e = 0
@@ -196,7 +326,7 @@ class GCode(object):
total_e += cur_e
cur_e = line.e
elif line.is_move() and line.e:
- if line.relative:
+ if line.relative_e:
cur_e += line.e
else:
cur_e = line.e
@@ -210,6 +340,8 @@ def main():
print "usage: %s filename.gcode" % sys.argv[0]
return
+# d = [i.replace("\n","") for i in open(sys.argv[1])]
+# gcode = GCode(d)
gcode = GCode(list(open(sys.argv[1])))
gcode.measure()
@@ -219,6 +351,8 @@ def main():
print "\tY: %0.02f - %0.02f (%0.02f)" % (gcode.ymin,gcode.ymax,gcode.depth)
print "\tZ: %0.02f - %0.02f (%0.02f)" % (gcode.zmin,gcode.zmax,gcode.height)
print "Filament used: %0.02fmm" % gcode.filament_length()
+ print "Number of layers: %d" % gcode.num_layers()
+
if __name__ == '__main__':
main()
diff --git a/plater.png b/plater.png
new file mode 100644
index 0000000..a4ef9e5
Binary files /dev/null and b/plater.png differ
diff --git a/printcore.py b/printcore.py
index bb6501c..3350761 100755
--- a/printcore.py
+++ b/printcore.py
@@ -222,6 +222,7 @@ class printcore():
def pause(self):
"""Pauses the print, saving the current position.
"""
+ if not self.printing: return False
self.paused = True
self.printing = False
self.print_thread.join()
@@ -230,6 +231,7 @@ class printcore():
def resume(self):
"""Resumes a paused print.
"""
+ if not self.paused: return False
self.paused = False
self.printing = True
self.print_thread = Thread(target = self._print)
@@ -287,6 +289,8 @@ class printcore():
self.sentlines = {}
self.log = []
self.sent = []
+ self.print_thread.join()
+ self.print_thread = None
if self.endcb:
#callback for printing done
try: self.endcb()
diff --git a/printrun/gui.py b/printrun/gui.py
index 09f7908..7e261d5 100644
--- a/printrun/gui.py
+++ b/printrun/gui.py
@@ -223,7 +223,7 @@ class MainToolbar(wx.BoxSizer):
root.serialport = wx.ComboBox(root.panel, -1,
choices = root.scanserial(),
- style = wx.CB_DROPDOWN, size = (100, 25))
+ style = wx.CB_DROPDOWN, size = (150, 25))
root.serialport.SetToolTip(wx.ToolTip("Select Port Printer is connected to"))
root.rescanports()
self.Add(root.serialport)
diff --git a/printrun/webinterface.py b/printrun/webinterface.py
index bc0d564..bb9690b 100644
--- a/printrun/webinterface.py
+++ b/printrun/webinterface.py
@@ -23,7 +23,7 @@ from printrun.printrun_utils import configfile, imagefile, sharedfile
users = {}
def PrintHeader():
- return '\n
\n\n"
pageText+="
\n"
- pageText+="
- Connect
\n"
- pageText+="- Disconnect
\n"
- pageText+="- Reset
\n"
- pageText+="- Print
\n"
- pageText+="- Pause
\n"
+ pageText+="- Connect
\n"
+ pageText+="- Disconnect
\n"
+ pageText+="- Reset
\n"
+ pageText+="- Print
\n"
+ pageText+="- Pause
\n"
for i in gPronterPtr.cpbuttons:
- pageText+="- "+i[0]+"
\n"
+ pageText+="- "+i.label+"
\n"
#for i in gPronterPtr.custombuttons:
# print(str(i));
@@ -303,38 +303,38 @@ class WebInterface(object):
pageText+="
"
pageText+='"
pageText+="
\n" #endxy
pageText+="
"
pageText+="
![](/images/control_z.png)
"
pageText+='
"
#TODO Map Z Moves
pageText+="
\n" #endz
@@ -374,11 +374,14 @@ def KillWebInterfaceThread():
cherrypy.engine.exit()
def StartWebInterfaceThread(webInterface):
- current_dir = os.path.dirname(os.path.abspath(__file__))
+ current_dir = os.path.dirname(os.path.abspath(__file__))
cherrypy.config.update({'engine.autoreload_on':False})
cherrypy.config.update(configfile(webInterface.pface.web_config or "http.config"))
conf = {'/css/style.css': {'tools.staticfile.on': True,
- 'tools.staticfile.filename': sharedfile('css/style.css'),
+ 'tools.staticfile.filename': sharedfile('web/css/style.css'),
+ },
+ '/js/asyncCommand.js': {'tools.staticfile.on': True,
+ 'tools.staticfile.filename': sharedfile('web/js/asyncCommand.js'),
},
'/images/control_xy.png': {'tools.staticfile.on': True,
'tools.staticfile.filename': imagefile('control_xy.png'),
diff --git a/pronsole.png b/pronsole.png
new file mode 100644
index 0000000..d0c745d
Binary files /dev/null and b/pronsole.png differ
diff --git a/pronsole.py b/pronsole.py
index 982665b..6bcae83 100755
--- a/pronsole.py
+++ b/pronsole.py
@@ -131,6 +131,14 @@ def estimate_duration(g):
#print "Total Duration: " #, time.strftime('%H:%M:%S', time.gmtime(totalduration))
return "{0:d} layers, ".format(int(layercount)) + str(datetime.timedelta(seconds = int(totalduration)))
+def confirm():
+ y_or_n = raw_input("y/n: ")
+ if y_or_n == "y":
+ return True
+ elif y_or_n != "n":
+ return confirm()
+ return False
+
class Settings:
#def _temperature_alias(self): return {"pla":210, "abs":230, "off":0}
#def _temperature_validate(self, v):
@@ -183,15 +191,46 @@ class Settings:
def _all_settings(self):
return dict([(k, getattr(self, k)) for k in self.__dict__.keys() if not k.startswith("_")])
+class Status:
+
+ def __init__(self):
+ self.extruder_temp = 0
+ self.extruder_temp_target = 0
+ self.bed_temp = 0
+ self.bed_temp_target = 0
+ self.print_job = None
+ self.print_job_progress = 1.0
+
+ def update_tempreading(self, tempstr):
+ r = tempstr.split()
+ # eg. r = ["ok", "T:20.5", "/0.0", "B:0.0", "/0.0", "@:0"]
+ if len(r) == 6:
+ self.extruder_temp = float(r[1][2:])
+ self.extruder_temp_target = float(r[2][1:])
+ self.bed_temp = float(r[3][2:])
+ self.bed_temp_target = float(r[4][1:])
+
+ @property
+ def bed_enabled(self):
+ return self.bed_temp != 0
+
+ @property
+ def extruder_enabled(self):
+ return self.extruder_temp != 0
+
+
+
class pronsole(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self)
if not READLINE:
self.completekey = None
+ self.status = Status()
+ self.dynamic_temp = False
self.p = printcore.printcore()
self.p.recvcb = self.recvcb
self.recvlisteners = []
- self.prompt = "PC>"
+ self.in_macro = False
self.p.onlinecb = self.online
self.f = None
self.listing = 0
@@ -230,6 +269,55 @@ class pronsole(cmd.Cmd):
self.webrequested = False
self.web_config = None
self.web_auth_config = None
+ self.promptstrs = {"offline" : "%(bold)suninitialized>%(normal)s ",
+ "fallback" : "%(bold)sPC>%(normal)s ",
+ "macro" : "%(bold)s..>%(normal)s ",
+ "online" : "%(bold)sT:%(extruder_temp_fancy)s %(progress_fancy)s >%(normal)s "}
+
+ def promptf(self):
+ """A function to generate prompts so that we can do dynamic prompts. """
+ if self.in_macro:
+ promptstr = self.promptstrs["macro"]
+ elif not self.p.online:
+ promptstr = self.promptstrs["offline"]
+ elif self.status.extruder_enabled:
+ promptstr = self.promptstrs["online"]
+ else:
+ promptstr = self.promptstrs["fallback"]
+ if not "%" in promptstr:
+ return promptstr
+ else:
+ specials = {}
+ specials["extruder_temp"] = str(int(self.status.extruder_temp))
+ specials["extruder_temp_target"] = str(int(self.status.extruder_temp_target))
+ if self.status.extruder_temp_target == 0:
+ specials["extruder_temp_fancy"] = str(int(self.status.extruder_temp))
+ else:
+ specials["extruder_temp_fancy"] = "%s/%s" % (str(int(self.status.extruder_temp)), str(int(self.status.extruder_temp_target)))
+ if self.p.printing:
+ progress = int(1000*float(self.p.queueindex)/len(self.p.mainqueue)) / 10
+ elif self.sdprinting:
+ progress = self.percentdone
+ else:
+ progress = 0.0
+ specials["progress"] = str(progress)
+ if self.p.printing or self.sdprinting:
+ specials["progress_fancy"] = str(progress) +"%"
+ else:
+ specials["progress_fancy"] = "?%"
+ specials["bold"] = "\033[01m"
+ specials["normal"] = "\033[00m"
+ return promptstr % specials
+
+ def postcmd(self, stop, line):
+ """ A hook we override to generate prompts after
+ each command is executed, for the next prompt.
+ We also use it to send M105 commands so that
+ temp info gets updated for the prompt."""
+ if self.p.online and self.dynamic_temp:
+ self.p.send_now("M105")
+ self.prompt = self.promptf()
+ return stop
def set_temp_preset(self, key, value):
if not key.startswith("bed"):
@@ -257,8 +345,8 @@ class pronsole(cmd.Cmd):
return baselist+glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*') +glob.glob("/dev/tty.*")+glob.glob("/dev/cu.*")+glob.glob("/dev/rfcomm*")
def online(self):
- print "Printer is now online"
- sys.stdout.write(self.prompt)
+ print "\rPrinter is now online"
+ sys.stdout.write(self.promptf())
sys.stdout.flush()
def help_help(self, l):
@@ -290,7 +378,8 @@ class pronsole(cmd.Cmd):
def end_macro(self):
if self.__dict__.has_key("onecmd"): del self.onecmd # remove override
- self.prompt = "PC>"
+ self.in_macro = False
+ self.prompt = self.promptf()
if self.cur_macro_def!="":
self.macros[self.cur_macro_name] = self.cur_macro_def
macro = self.compile_macro(self.cur_macro_name, self.cur_macro_def)
@@ -342,7 +431,8 @@ class pronsole(cmd.Cmd):
self.cur_macro_name = macro_name
self.cur_macro_def = ""
self.onecmd = self.hook_macro # override onecmd temporarily
- self.prompt = "..>"
+ self.in_macro = False
+ self.prompt = self.promptf()
def delete_macro(self, macro_name):
if macro_name in self.macros.keys():
@@ -520,6 +610,7 @@ class pronsole(cmd.Cmd):
def preloop(self):
print "Welcome to the printer console! Type \"help\" for a list of available commands."
+ self.prompt = self.promptf()
cmd.Cmd.preloop(self)
def do_connect(self, l):
@@ -813,10 +904,13 @@ class pronsole(cmd.Cmd):
def recvcb(self, l):
if "T:" in l:
self.tempreadings = l
+ self.status.update_tempreading(l)
tstring = l.rstrip()
if(tstring!="ok" and not tstring.startswith("ok T") and not tstring.startswith("T:") and not self.listing and not self.monitoring):
- print tstring
- sys.stdout.write(self.prompt)
+ if tstring[:5] == "echo:":
+ tstring = tstring[5:].lstrip()
+ print "\r" + tstring.ljust(15)
+ sys.stdout.write(self.promptf())
sys.stdout.flush()
for i in self.recvlisteners:
i(l)
@@ -848,16 +942,17 @@ class pronsole(cmd.Cmd):
def help_help(self):
self.do_help("")
- def tempcb(self, l):
- if "T:" in l:
- print l.replace("\r", "").replace("T", "Hotend").replace("B", "Bed").replace("\n", "").replace("ok ", "")
-
def do_gettemp(self, l):
+ if "dynamic" in l:
+ self.dynamic_temp = True
if self.p.online:
- self.recvlisteners+=[self.tempcb]
self.p.send_now("M105")
time.sleep(0.75)
- self.recvlisteners.remove(self.tempcb)
+ if not self.status.bed_enabled:
+ print "Hotend: %s/%s" % (self.status.extruder_temp, self.status.extruder_temp_target)
+ else:
+ print "Hotend: %s/%s" % (self.status.extruder_temp, self.status.extruder_temp_target)
+ print "Bed: %s/%s" % (self.status.bed_temp, self.status.bed_temp_target)
def help_gettemp(self):
print "Read the extruder and bed temperature."
@@ -869,6 +964,10 @@ class pronsole(cmd.Cmd):
l = l.replace(i, self.temps[i])
f = float(l)
if f>=0:
+ if f > 250:
+ print f, " is a high temperature to set your extruder to. Are you sure you want to do that?"
+ if not confirm():
+ return
if self.p.online:
self.p.send_now("M104 S"+l)
print "Setting hotend temperature to ", f, " degrees Celsius."
@@ -1045,9 +1144,22 @@ class pronsole(cmd.Cmd):
print "reverse -5 - EXTRUDES 5mm of filament at 300mm/min (5mm/s)"
def do_exit(self, l):
+ if self.status.extruder_temp_target != 0:
+ print "Setting extruder temp to 0"
+ self.p.send_now("M104 S0.0")
+ if self.status.bed_enabled:
+ if self.status.bed_temp_taret != 0:
+ print "Setting bed temp to 0"
+ self.p.send_now("M140 S0.0")
print "Disconnecting from printer..."
- self.p.disconnect()
+ print self.p.printing
+ if self.p.printing:
+ print "Are you sure you want to exit while printing?"
+ print "(this will terminate the print)."
+ if not confirm():
+ return False
print "Exiting program. Goodbye!"
+ self.p.disconnect()
return True
def help_exit(self):
@@ -1058,6 +1170,9 @@ class pronsole(cmd.Cmd):
if not self.p.online:
print "Printer is not online. Please connect first."
return
+ if not (self.p.printing or self.sdprinting):
+ print "Printer not printing. Please print something before monitoring."
+ return
print "Monitoring printer, use ^C to interrupt."
if len(l):
try:
@@ -1066,22 +1181,27 @@ class pronsole(cmd.Cmd):
print "Invalid period given."
print "Updating values every %f seconds."%(interval,)
self.monitoring = 1
+ prev_msg_len = 0
try:
- while(1):
+ while True:
self.p.send_now("M105")
if(self.sdprinting):
self.p.send_now("M27")
time.sleep(interval)
#print (self.tempreadings.replace("\r", "").replace("T", "Hotend").replace("B", "Bed").replace("\n", "").replace("ok ", ""))
- if(self.p.printing):
- print "Print progress: ", 100*float(self.p.queueindex)/len(self.p.mainqueue), "%"
-
- if(self.sdprinting):
- print "SD print progress: ", self.percentdone, "%"
-
- except:
+ if self.p.printing:
+ preface = "Print progress: "
+ progress = 100*float(self.p.queueindex)/len(self.p.mainqueue)
+ elif self.sdprinting:
+ preface = "Print progress: "
+ progress = self.percentdone
+ progress = int(progress*10)/10.0 #limit precision
+ prev_msg = preface + str(progress) + "%"
+ sys.stdout.write("\r" + prev_msg.ljust(prev_msg_len))
+ sys.stdout.flush()
+ prev_msg_len = len(prev_msg)
+ except KeyboardInterrupt:
print "Done monitoring."
- pass
self.monitoring = 0
def help_monitor(self):
@@ -1193,6 +1313,69 @@ class pronsole(cmd.Cmd):
self.onecmd(a)
self.processing_args = False
+
+ # We replace this function, defined in cmd.py .
+ # It's default behavior with reagrds to Ctr-C
+ # and Ctr-D doesn't make much sense...
+
+ def cmdloop(self, intro=None):
+ """Repeatedly issue a prompt, accept input, parse an initial prefix
+ off the received input, and dispatch to action methods, passing them
+ the remainder of the line as argument.
+
+ """
+
+ self.preloop()
+ if self.use_rawinput and self.completekey:
+ try:
+ import readline
+ self.old_completer = readline.get_completer()
+ readline.set_completer(self.complete)
+ readline.parse_and_bind(self.completekey+": complete")
+ except ImportError:
+ pass
+ try:
+ if intro is not None:
+ self.intro = intro
+ if self.intro:
+ self.stdout.write(str(self.intro)+"\n")
+ stop = None
+ while not stop:
+ if self.cmdqueue:
+ line = self.cmdqueue.pop(0)
+ else:
+ if self.use_rawinput:
+ try:
+ line = raw_input(self.prompt)
+ except EOFError:
+ print ""
+ should_exit = self.do_exit("")
+ if should_exit:
+ exit()
+ except KeyboardInterrupt:
+ print ""
+ line = ""
+ else:
+ self.stdout.write(self.prompt)
+ self.stdout.flush()
+ line = self.stdin.readline()
+ if not len(line):
+ line = ""
+ else:
+ line = line.rstrip('\r\n')
+ line = self.precmd(line)
+ stop = self.onecmd(line)
+ stop = self.postcmd(stop, line)
+ self.postloop()
+ finally:
+ if self.use_rawinput and self.completekey:
+ try:
+ import readline
+ readline.set_completer(self.old_completer)
+ except ImportError:
+ pass
+
+
if __name__ == "__main__":
interp = pronsole()
diff --git a/css/style.css b/web/css/style.css
similarity index 100%
rename from css/style.css
rename to web/css/style.css
diff --git a/web/js/asyncCommand.js b/web/js/asyncCommand.js
new file mode 100644
index 0000000..f37ec8c
--- /dev/null
+++ b/web/js/asyncCommand.js
@@ -0,0 +1,79 @@
+function pronterfaceWebInterface_setup(){
+ pronterfaceWebInterface_attachAsync();
+}
+
+function pronterfaceWebInterface_attachAsync(){
+
+ var list = [];
+ if(document.getElementsByClassName){
+ list = document.getElementsByClassName('command');
+ }else if(document.getElementsByTagName){
+ list = document.getElementsByTagName('a');
+ list.concat( document.getElementsByTagName('area') );
+ //TODO filter list via checking the className attributes
+ }else{
+ console && console.error && console.error('unable to gather list of elements');
+ return false;
+ }
+
+ for(var i=0; i < list.length; i++){
+ list[i].addEventListener && list[i].addEventListener( 'click', function(e){return pronterfaceWebInterface_asyncCommand(null, e);}, true );
+ list[i].attachEvent && list[i].attachEvent( 'onclick', function(e){return pronterfaceWebInterface_asyncCommand(null, e);} );
+ }
+
+ return true;
+}
+
+
+function pronterfaceWebInterface_asyncCommand( urlOrElement, event ){
+
+ if( ! urlOrElement && event.target)
+ urlOrElement = event.target;
+
+ var url = null;
+ if( typeof urlOrElement == 'string' ){
+ url = urlOrElement;
+ }else{
+ url = urlOrElement&&urlOrElement.href;
+ }
+
+ if( typeof url != 'string' ){
+ console && console.error && console.error('url not a string', urlOrElement, url);
+ return true;
+ }
+
+ var httpRequest;
+ if (window.XMLHttpRequest) { // Mozilla, Safari, ...
+ httpRequest = new XMLHttpRequest();
+ } else if (window.ActiveXObject) { // IE 8 and older
+ httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
+ }
+
+ if( ! httpRequest ){
+ alert('no AJAX available?');
+ // follow link
+ return true;
+ }
+
+ //onreadystatechange
+ //onerror
+ httpRequest.open( 'GET', url, true);
+ httpRequest.send(null);
+
+ // don't follow link
+ if( event ){
+ event.stopImmediatePropagation && event.stopImmediatePropagation();
+ event.defaultPrevented = true;
+ event.preventDefault && event.preventDefault();
+ }
+ return false;
+}
+
+
+if (document.addEventListener) {
+ document.addEventListener("DOMContentLoaded", pronterfaceWebInterface_setup, false);
+} else if (document.attachEvent) {
+ document.attachEvent("onreadystatechange", pronterfaceWebInterface_setup);
+} else {
+ document.onload = pronterfaceWebInterface_setup;
+}