The best I can come up with so far is my use of a generic view (I'm just
getting into this web app stuff). I suspect that I need to elaborate
index.html. Sound right?
Here's my code:
Control -- dispatch_board.py and default.py
#-------------------------------------------------------------------------------
# Name: dispatch_board
# Purpose:
#
# Author: Frank Hall
#
# Created: 26/12/2011
# Copyright:
# Licence: <your licence>
#-------------------------------------------------------------------------------
#!/usr/bin/env python
import re
import pickle
def quote(text):
return str(text).replace('\\', '\\\\').replace("'", "\\'")
def valid_key(key):
return re.match('L\d+D\d+', key)
def load_key(row, col):
return 'L%sD%s'%(row, col)
def jq_cmd(key, value):
return "jQuery('#%s').val('%s');" % (key, quote(value))
class Node:
def __init__(self, name, value, size=4, url='.', readonly=True):
self.name = name
self.value = value
self.size = size
self.url = url
self.readonly = readonly
def xml(self):
return """<input name="%s" id="%s" value="%s" size="%s"
onfocus="ajax('%s/focus',['%s'], ':eval');"
onmouseup="ajax('%s/mouseup',['%s'], ':eval');" %s/>
""" % (self.name, self.name, self.value, self.size,
self.url, self.name, self.url, self.name,
(self.readonly and 'readonly ') or '')
def __repr__(self):
return self.value
class DispatchBoard:
def dumps(self):
return pickle.dumps(self)
@staticmethod
def loads(data):
return pickle.loads(data)
def load_row_col(self, key):
if key == '':
(row, col) = (-1, -1)
else:
(row, col) = key[1:].split('D')
return (int(row), int(col))
def get_load_value(self, row, col):
key = load_key(row, col)
return self.nodes[key].value
def set_load_value(self, row, col, value):
key = load_key(row, col)
self.nodes[key].value = value
jquery = jq_cmd(key, value)
return jquery
def delete_load(self, row, col):
rnew = self.rows - 1
r = row
jquery = ''
while r < rnew:
value = self.get_load_value(r + 1, col)
jquery += self.set_load_value(r, col, value)
r = r + 1
jquery += self.set_load_value(r, col, '')
return jquery
def insert_load(self, row, col, value, after = False):
rnew = row
if after:
rnew = rnew + 1
r = self.rows - 1
jquery = ''
while r > rnew:
value_move = self.get_load_value(r - 1, col)
jquery += self.set_load_value(r, col, value_move)
r = r - 1
if r == rnew:
jquery += self.set_load_value(r, col, value)
return jquery
def move_load(self, from_row, from_col, to_row, to_col, after = False):
value = self.get_load_value(from_row, from_col)
jquery = self.insert_load(to_row, to_col, value, after)
jquery += self.delete_load(from_row, from_col)
return jquery
def mouseup(self, key):
if (self.drag_key != '') & (key != self.drag_key):
(from_row, from_col) = self.load_row_col(self.drag_key)
(to_row, to_col) = self.load_row_col(key)
jquery = self.move_load(from_row, from_col, to_row, to_col)
else:
jquery = ''
self.drag_key = ''
return jquery
def focus(self, key):
self.drag_key = key
def process(self, callback_args):
##call this in action that creates table, it will handle ajax
callbacks
func = callback_args['func']
key = callback_args['key']
if func == 'focus':
return self.focus(key)
elif func == 'mouseup':
return self.mouseup(key)
def cell(self, key, value, size=4, readonly=True):
##key is the name of the cell
##value is the initial value of the cell.
if not valid_key(key):
raise SyntaxError, "Invalid cell name: %s" % key
self.nodes[key] = Node(key, value, size, self.url, readonly)
def xml(self):
import gluon.html
(DIV, TABLE, TR, TD, TH, BR) = \
(gluon.html.DIV, gluon.html.TABLE, gluon.html.TR, gluon.html.TD,
gluon.html.TH, gluon.html.BR)
xml_board = DIV(TABLE( \
TR(TH(),*[TH('Driver %s' % c) \
for c in range(self.cols)]), \
*[TR(TH('Load %s' % r), \
*[TD(self.nodes[load_key(r, c)]) \
for c in range(self.cols)]) \
for r in range(self.rows)])).xml()
return xml_board
def __init__(self, rows, cols, size=4, url='.', readonly=True):
self.rows = rows
self.cols = cols
self.size = size
self.url = url
self.nodes = {}
self.error = 'ERROR: %(error)s'
self.drag_key = ''
for k in xrange(rows*cols):
key = load_key(k/cols, k%cols)
self.cell(key, key, size, readonly)
if __name__ == '__main__':
pass
# -*- coding: utf-8 -*-
# this file is released under public domain and you can use without
limitations
#########################################################################
## default.py
#########################################################################
from dispatch_board import DispatchBoard
board_rows = 5
board_cols = 5
cell_size = 10
board_cache_key = 'board1'
board_callback = 'callback'
def callback():
callback_args = {}
callback_args['func'] = request.args(0)
callback_args['key'] = request.vars.keys()[0]
return cache.ram(board_cache_key, lambda: None,
None).process(callback_args)
def index():
board = cache.ram(board_cache_key,
lambda: DispatchBoard(board_rows, board_cols,
cell_size, \
URL(r=request, f=board_callback)), 0)
board.nodes['L0D3'].value = 'Frank'
return dict(board=board)
View -- index.html:
{{extend 'layout.html'}}
{{=board}}