from django.utils.translation import ugettext as _ from django.forms import MultiValueField from django.forms.widgets import Widget, Select from django.utils.safestring import mark_safe from django.utils import simplejson """ var categorySelect = function(el, target, tree){ var list = tree[el.getValue()]; target.setTextValue(''); for (var key = 0; key < list.length; key++){ var option = document.createElement('option'); option.setValue(list[key][0]); option.setTextValue(list[key][1]); target.appendChild(option); } }; """ class CategorySelect(Widget): category_name = '%s_category' def __init__(self, choice_tree, attrs=None): self.attrs = attrs or {} category_choices = [] choices_map = {} for cat_id, cat_label, subcats in choice_tree: category_choices += ((cat_id, cat_label),) choices_map[cat_id] = subcats self.category_choices = category_choices self.choices_map = choices_map def value_from_datadict(self, data, files, name): cat_value = data.get(self.category_name % name, '') subcat_value = data.get(name, '') return cat_value, subcat_value def render(self, name, value, attrs={}): # Value is id of the bottom choice. category_value = None choices = () if value: for cat_id, subcats in self.choices_map.items(): for subcat_id, subcat_label in subcats: if str(subcat_id) == str(value): category_value = str(cat_id) choices = subcats break else: category_value = self.category_choices[0][1] choices = self.choices_map.values()[0] output = [] category_id = 'id_%s_category' % name category_attrs = { 'id': category_id, 'onchange': 'categorySelect(this, document.getElementById(\'id_%s\'), %s);' % \ (name, simplejson.dumps(self.choices_map)) } output.append(Select().render(self.category_name % name, category_value, category_attrs, self.category_choices)) output.append(Select().render(name, value, attrs, choices)) return mark_safe(u'\n'.join(output)) class CategoryField(MultiValueField): FACEBOOK_EVENT_SUBCATEGORIES = [ _('Birthday Party'), _('Cocktail Party'), _('Club Party'), _('Potluck'), _('Fraternity/Sorority Party'), _('Business Meeting'), _('Barbecue'), _('Card Night'), _('Dinner Party'), _('Holiday Party'), _('Night of Mayhem'), _('Movie/TV Night'), _('Drinking Games'), _('Bar Night'), _('LAN Party'), _('Brunch'), _('Mixer'), _('Slumber Party'), _('Erotic Party'), _('Benefit'), _('Goodbye Party'), _('House Party'), _('Reunion'), _('Fundraiser'), _('Protest'), _('Rally'), _('Class'), _('Lecture'), _('Office Hours'), _('Workshop'), _('Club/Group Meeting'), _('Convention'), _('Dorm/House Meeting'), _('Informational Meeting'), _('Audition'), _('Exhibit'), _('Jam Session'), _('Listening Party'), _('Opening'), _('Performance'), _('Preview'), _('Recital'), _('Rehearsal'), _('Pep Rally'), _('Pick-Up'), _('Sporting Event'), _('Sports Practice'), _('Tournament'), _('Camping Trip'), _('Daytrip'), _('Group Trip'), _('Roadtrip'), _('Carnival'), _('Ceremony'), _('Festival'), _('Flea Market'), _('Retail')] FACEBOOK_EVENTS = ( (_('Party'), (0,23)), (_('Causes'), (23,27)), (_('Education'), (27,31)), (_('Meetings'), (31,36)), (_('Music/Arts'), (36,45)), (_('Sports'), (45,48)), (_('Trips'), (48,53)), (_('Other'), (53,-1)) ) def __init__(self, *args, **kwargs): super(CategoryField, self).__init__(widget=CategorySelect(self.get_facebook_event_tree()), *args, **kwargs) def get_facebook_event_tree(self): # Output a tree structure, more easily handled by client side code results = [] for i, category in enumerate(self.FACEBOOK_EVENTS): category_label, slices = category s1, s2 = slices subcats = zip(range(*slices), self.FACEBOOK_EVENT_SUBCATEGORIES[s1:s2]) results += ((i, category_label, subcats),) return results def clean(self, value): try: if [int(b) for b in value if b]: return value except ValueError: raise forms.ValidationError(_('You must select a category and subcategory for your event.')) return [None, None]