AJAXForeignKey: forms.py

File forms.py, 5.0 KB (added by Michael Axiak <axiak@…>, 18 years ago)

form field definition

Line 
1from django import oldforms
2from django.template.defaultfilters import addslashes
3import re
4
5get_id_re = re.compile('\D*(\d+)\D$')
6
7class AjaxForeignKeyFormField(oldforms.FormField):
8 def __init__(self, field_name, field,
9 is_required=False, validator_list=None,
10 member_name=None, ajax_func = None, width=None,
11 help_text = None):
12
13 self.field_name = field_name
14 self.field = field
15 self.is_required = is_required
16 self.help_text = help_text
17
18 if width is None:
19 self.width = '25em'
20 else:
21 self.width = width
22
23 if ajax_func is None:
24 self.ajax_func = 'ajax_autocomplete'
25 else:
26 self.ajax_func = ajax_func
27
28 if validator_list is None:
29 validator_list = []
30
31 self.validator_list = validator_list
32
33 def extract_data(self, data):
34 return data.get(self.field.attname, '')
35
36
37 def render(self, data):
38 """
39 Renders the actual ajax widget.
40 """
41
42 init_val = data
43
44 if data:
45 objects = self.field.rel.to.objects.filter(pk = data)
46 if objects.count() == 1:
47 obj = objects[0]
48 if hasattr(obj, 'ajax_str'):
49 init_val = obj.ajax_str() + " (%s)" % data
50 else:
51 init_val = obj.__str__() + " (%s)" % data
52 else:
53 data = init_val = ''
54
55
56 fn = self.field_name
57 related_model = self.field.rel.to
58
59 model_module = related_model.__module__
60 model_name = related_model.__name__
61
62 javascript = """
63<script type="text/javascript">
64<!--
65
66document.getElementById("id_%s").value = "%s";
67
68var %s_data = new YAHOO.widget.DS_XHR("/admin/ajax_autocomplete/",
69 ['result','ajax_str','id']);
70
71%s_data.scriptQueryParam = "ajax_data";
72%s_data.scriptQueryAppend = "model_module=%s&model_name=%s&ajax_func=%s";
73%s_data.connTimeout = 3000;
74
75var autocomp__%s = new YAHOO.widget.AutoComplete("id_%s","id_%s__container",%s_data);
76
77autocomp__%s.allowBrowserAutocomplete = false;
78//autocomp__%s.typeAhead = true;
79autocomp__%s.animVert = true;
80autocomp__%s.queryDelay = .2;
81autocomp__%s.maxCacheEntries = 60;
82autocomp__%s.animSpeed = .5;
83autocomp__%s.useShadow = true;
84autocomp__%s.useIFrame = true;
85
86
87YAHOO.util.Event.addListener(window, "load", function (e) {
88 var elements = YAHOO.util.Dom.getElementsByClassName('add-another', 'a');
89 for (var i=0; i<elements.length; i++) {
90 elements[i].style.display = 'none';
91 }
92 var elements = YAHOO.util.Dom.getElementsByClassName('form-row', 'div');
93 for (var i=0; i< elements.length; i++) {
94 elements[i].style.overflow = 'visible';
95 if (YAHOO.util.Dom.getElementsByClassName('yui_autocomplete','div', elements[i]).length > 0) {
96 elements[i].style.paddingBottom = '12.5em';
97 }
98 }
99});
100
101//-->
102</script>""" % \
103 (fn, addslashes(init_val),
104 fn, fn, fn, model_module, model_name, self.ajax_func,
105 fn, fn, fn, fn, fn, fn, fn, fn, fn, fn, fn, fn, fn)
106
107 css = """
108<style type="text/css">
109 /* Taken from Yahoo... */
110 #id_%s__yui_autocomplete {position:relative;width:%s;margin-bottom:1em;}/* set width of widget here*/
111 #id_%s__yui_autocomplete {z-index:0} /* for IE z-index of absolute divs inside relative divs issue */
112 #id_%s__yui_autocomplete input {_position:absolute;width:100%%;height:1.4em;z-index:0;} /* abs for ie quirks */
113 #id_%s__container {position:relative; width:100%%;}
114 #id_%s__container .yui-ac-content {position:absolute;width:100%%;border:1px solid #ccc;background:#fff;overflow:hidden;z-index:9050;}
115 #id_%s__container .yui-ac-shadow {position:absolute;margin:.3em;width:100%%;background:#eee;z-index:8000;}
116 #id_%s__container ul {padding:5px 0;width:100%%; list-item-type: none;margin-left: 0; padding-left: 0;z-index:9000;}
117 #id_%s__container li {padding:0 5px;cursor:default;white-space:nowrap;padding-left: 0; margin-left: 0;}
118 #id_%s__container li.yui-ac-highlight {background:#9cf;z-index:9000;}
119 #id_%s__container li.yui-ac-prehighlight {background:#CCFFFF;z-index:9000;}
120 .yui-ac-bd { padding:0; margin: 0; z-index:9000;}
121</style>
122""" % \
123 (fn,self.width,fn,fn,fn,fn,fn,fn,fn,fn,fn)
124
125 html = """
126<div class="container" style="position: relative;">
127<div class="yui_autocomplete" id="id_%s__yui_autocomplete">
128 <input type="text" id="id_%s" name="%s" class="vCharField" value="%s" />
129 <div id="id_%s__container" class="yui_container"></div>
130</div>
131</div>
132
133""" % (fn,fn,fn,addslashes(init_val),fn)
134
135 return css + html + javascript
136
137 def prepare(self, new_data):
138 id = new_data.get(self.field_name, None)
139 if id:
140 try:
141 id = int(id)
142 except ValueError:
143 match = get_id_re.match(id)
144 id = match.groups()[0]
145 new_data[self.field_name] = id
Back to Top