Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Convert owner and team member project form fields to autocomplete.

add django-selectable
Fix bug 746387.
  • Loading branch information...
commit 1aa8411c22dee7fb24190f85c3ba8ecba20621c2 1 parent 4702110
Paul McLanahan authored April 18, 2012

Showing 61 changed files with 3,711 additions and 15 deletions. Show diff stats Hide diff stats

  1. 5  apps/projects/forms.py
  2. 9  apps/projects/templates/projects/edit.html
  3. 14  apps/projects/tests.py
  4. 28  apps/users/lookups.py
  5. BIN  media/css/jq-ui-smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
  6. BIN  media/css/jq-ui-smoothness/images/ui-bg_flat_75_ffffff_40x100.png
  7. BIN  media/css/jq-ui-smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
  8. BIN  media/css/jq-ui-smoothness/images/ui-bg_glass_65_ffffff_1x400.png
  9. BIN  media/css/jq-ui-smoothness/images/ui-bg_glass_75_dadada_1x400.png
  10. BIN  media/css/jq-ui-smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
  11. BIN  media/css/jq-ui-smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
  12. BIN  media/css/jq-ui-smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
  13. BIN  media/css/jq-ui-smoothness/images/ui-icons_222222_256x240.png
  14. BIN  media/css/jq-ui-smoothness/images/ui-icons_2e83ff_256x240.png
  15. BIN  media/css/jq-ui-smoothness/images/ui-icons_454545_256x240.png
  16. BIN  media/css/jq-ui-smoothness/images/ui-icons_888888_256x240.png
  17. BIN  media/css/jq-ui-smoothness/images/ui-icons_cd0a0a_256x240.png
  18. 564  media/css/jq-ui-smoothness/jquery-ui-1.8.19.custom.css
  19. 13  media/css/main.less
  20. 125  media/js/libs/jquery-ui-1.8.19.custom.min.js
  21. 37  media/selectable/css/dj.selectable.css
  22. 325  media/selectable/js/jquery.dj.selectable.js
  23. 0  python/example/core/__init__.py b/vendor-local/lib/python/example/core/__init__.py
  24. 1  requirements/prod.txt
  25. 13  settings.py
  26. 8  urls.py
  27. 84  vendor-local/lib/python/django_selectable-0.4.1-py2.7.egg-info/PKG-INFO
  28. 44  vendor-local/lib/python/django_selectable-0.4.1-py2.7.egg-info/SOURCES.txt
  29. 1  vendor-local/lib/python/django_selectable-0.4.1-py2.7.egg-info/dependency_links.txt
  30. 64  vendor-local/lib/python/django_selectable-0.4.1-py2.7.egg-info/installed-files.txt
  31. 1  vendor-local/lib/python/django_selectable-0.4.1-py2.7.egg-info/not-zip-safe
  32. 2  vendor-local/lib/python/django_selectable-0.4.1-py2.7.egg-info/top_level.txt
  33. 53  vendor-local/lib/python/example/core/admin.py
  34. 91  vendor-local/lib/python/example/core/forms.py
  35. 39  vendor-local/lib/python/example/core/lookups.py
  36. 26  vendor-local/lib/python/example/core/models.py
  37. 23  vendor-local/lib/python/example/core/tests.py
  38. 8  vendor-local/lib/python/example/core/urls.py
  39. 43  vendor-local/lib/python/example/core/views.py
  40. 24  vendor-local/lib/python/selectable/__init__.py
  41. 138  vendor-local/lib/python/selectable/base.py
  42. 10  vendor-local/lib/python/selectable/exceptions.py
  43. 3  vendor-local/lib/python/selectable/forms/__init__.py
  44. 19  vendor-local/lib/python/selectable/forms/base.py
  45. 92  vendor-local/lib/python/selectable/forms/fields.py
  46. 237  vendor-local/lib/python/selectable/forms/widgets.py
  47. 3  vendor-local/lib/python/selectable/models.py
  48. 69  vendor-local/lib/python/selectable/registry.py
  49. 37  vendor-local/lib/python/selectable/static/selectable/css/dj.selectable.css
  50. 325  vendor-local/lib/python/selectable/static/selectable/js/jquery.dj.selectable.js
  51. 44  vendor-local/lib/python/selectable/tests/__init__.py
  52. 121  vendor-local/lib/python/selectable/tests/base.py
  53. 122  vendor-local/lib/python/selectable/tests/fields.py
  54. 86  vendor-local/lib/python/selectable/tests/forms.py
  55. 220  vendor-local/lib/python/selectable/tests/functests.py
  56. 45  vendor-local/lib/python/selectable/tests/runtests.py
  57. 8  vendor-local/lib/python/selectable/tests/urls.py
  58. 97  vendor-local/lib/python/selectable/tests/views.py
  59. 379  vendor-local/lib/python/selectable/tests/widgets.py
  60. 10  vendor-local/lib/python/selectable/urls.py
  61. 16  vendor-local/lib/python/selectable/views.py
5  apps/projects/forms.py
@@ -2,10 +2,15 @@
2 2
 
3 3
 from django import forms
4 4
 
  5
+from selectable.forms import AutoCompleteSelectMultipleField
  6
+
5 7
 from .models import Project, Link
  8
+from users.lookups import ProfileLookup
6 9
 
7 10
 
8 11
 class ProjectForm(forms.ModelForm):
  12
+    owners = AutoCompleteSelectMultipleField(ProfileLookup)
  13
+    team_members = AutoCompleteSelectMultipleField(ProfileLookup)
9 14
 
10 15
     class Meta:
11 16
         model = Project
9  apps/projects/templates/projects/edit.html
@@ -8,6 +8,15 @@
8 8
 {% block page_id %}project_edit{% endblock %}
9 9
 {% block section_class %}projects{% endblock %}
10 10
 
  11
+{% block extrahead %}
  12
+  {{ css('selectable') }}
  13
+  {{ form.media.css }}
  14
+{% endblock %}
  15
+
  16
+{% block js %}
  17
+  {{ js('selectable') }}
  18
+{% endblock %}
  19
+
11 20
 {% block breadcrumbs -%}
12 21
   {{ breadcrumbs(
13 22
       (url('projects_all'), _('Projects')),
14  apps/projects/tests.py
@@ -163,8 +163,8 @@ def test_owner_can_update_project(self):
163 163
             'description': 'All The Dude ever wanted... was his rug back.',
164 164
             'long_description': new_desc,
165 165
             'topics': [self.topic.id],
166  
-            'team_members': [self.profile.pk],
167  
-            'owners': [self.owner_profile.pk],
  166
+            'team_members_1': [self.profile.pk],
  167
+            'owners_1': [self.owner_profile.pk],
168 168
         })
169 169
         proj = Project.objects.get(pk=self.project.pk)
170 170
         self.assertEqual(proj.name, new_name)
@@ -186,8 +186,8 @@ def test_updating_project_members(self):
186 186
             'description': self.project.description,
187 187
             'long_description': self.project.long_description,
188 188
             'topics': [self.topic.id],
189  
-            'team_members': [self.profile.pk, self.owner_profile.pk],
190  
-            'owners': [self.owner_profile.pk],
  189
+            'team_members_1': [self.profile.pk, self.owner_profile.pk],
  190
+            'owners_1': [self.owner_profile.pk],
191 191
             })
192 192
         self.assertTrue(self.owner_profile in self.project.team_members.all())
193 193
         self.assertTrue(self.profile in self.project.team_members.all())
@@ -201,7 +201,7 @@ def test_owner_cannot_inject_xss(self):
201 201
         self.client.post('/en-US' + self.project_xss.get_edit_url(), {
202 202
             'topics': [self.topic.id],
203 203
             'team_members': [self.profile.pk],
204  
-            'owners': [self.owner_profile.pk],
  204
+            'owners_1': [self.owner_profile.pk],
205 205
         })
206 206
         proj = Project.objects.get(pk=self.project_xss.pk)
207 207
         self.assertEqual(proj.long_description, "alert('i am evil');")
@@ -221,8 +221,8 @@ def test_non_owner_cannot_update_project(self):
221 221
             'description': 'All The Dude ever wanted... was his rug back.',
222 222
             'long_description': new_desc,
223 223
             'topics': [self.topic.id],
224  
-            'team_members': [self.profile.pk],
225  
-            'owners': [self.owner_profile.pk],
  224
+            'team_members_1': [self.profile.pk],
  225
+            'owners_1': [self.owner_profile.pk],
226 226
             })
227 227
         proj = Project.objects.get(pk=self.project.pk)
228 228
         self.assertEqual(proj.name, self.project.name)
28  apps/users/lookups.py
... ...
@@ -0,0 +1,28 @@
  1
+from selectable.base import ModelLookup
  2
+from selectable.registry import registry
  3
+
  4
+from users.models import Profile
  5
+
  6
+
  7
+class ProfileLookup(ModelLookup):
  8
+    model = Profile
  9
+    search_fields = (
  10
+        'name__icontains',
  11
+        'user__email__icontains',
  12
+    )
  13
+
  14
+    def get_item_value(self, item):
  15
+        """Display for currently selected item"""
  16
+        return item.display_name
  17
+
  18
+    def get_item_label(self, item):
  19
+        """Display for choice listings"""
  20
+        return item.display_name
  21
+
  22
+    def get_queryset(self):
  23
+        qs = super(ProfileLookup, self).get_queryset()
  24
+        qs.order_by('name')
  25
+        return qs
  26
+
  27
+
  28
+registry.register(ProfileLookup)
BIN  media/css/jq-ui-smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
BIN  media/css/jq-ui-smoothness/images/ui-bg_flat_75_ffffff_40x100.png
BIN  media/css/jq-ui-smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
BIN  media/css/jq-ui-smoothness/images/ui-bg_glass_65_ffffff_1x400.png
BIN  media/css/jq-ui-smoothness/images/ui-bg_glass_75_dadada_1x400.png
BIN  media/css/jq-ui-smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
BIN  media/css/jq-ui-smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
BIN  media/css/jq-ui-smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
BIN  media/css/jq-ui-smoothness/images/ui-icons_222222_256x240.png
BIN  media/css/jq-ui-smoothness/images/ui-icons_2e83ff_256x240.png
BIN  media/css/jq-ui-smoothness/images/ui-icons_454545_256x240.png
BIN  media/css/jq-ui-smoothness/images/ui-icons_888888_256x240.png
BIN  media/css/jq-ui-smoothness/images/ui-icons_cd0a0a_256x240.png
564  media/css/jq-ui-smoothness/jquery-ui-1.8.19.custom.css
... ...
@@ -0,0 +1,564 @@
  1
+/*!
  2
+ * jQuery UI CSS Framework 1.8.19
  3
+ *
  4
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
  5
+ * Dual licensed under the MIT or GPL Version 2 licenses.
  6
+ * http://jquery.org/license
  7
+ *
  8
+ * http://docs.jquery.com/UI/Theming/API
  9
+ */
  10
+
  11
+/* Layout helpers
  12
+----------------------------------*/
  13
+.ui-helper-hidden { display: none; }
  14
+.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
  15
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
  16
+.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
  17
+.ui-helper-clearfix:after { clear: both; }
  18
+.ui-helper-clearfix { zoom: 1; }
  19
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
  20
+
  21
+
  22
+/* Interaction Cues
  23
+----------------------------------*/
  24
+.ui-state-disabled { cursor: default !important; }
  25
+
  26
+
  27
+/* Icons
  28
+----------------------------------*/
  29
+
  30
+/* states and images */
  31
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
  32
+
  33
+
  34
+/* Misc visuals
  35
+----------------------------------*/
  36
+
  37
+/* Overlays */
  38
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
  39
+
  40
+
  41
+/*!
  42
+ * jQuery UI CSS Framework 1.8.19
  43
+ *
  44
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
  45
+ * Dual licensed under the MIT or GPL Version 2 licenses.
  46
+ * http://jquery.org/license
  47
+ *
  48
+ * http://docs.jquery.com/UI/Theming/API
  49
+ *
  50
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
  51
+ */
  52
+
  53
+
  54
+/* Component containers
  55
+----------------------------------*/
  56
+.ui-widget .ui-widget { font-size: 1em; }
  57
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
  58
+.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
  59
+.ui-widget-content a { color: #222222; }
  60
+.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
  61
+.ui-widget-header a { color: #222222; }
  62
+
  63
+/* Interaction states
  64
+----------------------------------*/
  65
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
  66
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
  67
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
  68
+.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; }
  69
+.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
  70
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
  71
+.ui-widget :active { outline: none; }
  72
+
  73
+/* Interaction Cues
  74
+----------------------------------*/
  75
+.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight  {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
  76
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
  77
+.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
  78
+.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
  79
+.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
  80
+.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
  81
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary,  .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
  82
+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
  83
+
  84
+/* Icons
  85
+----------------------------------*/
  86
+
  87
+/* states and images */
  88
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
  89
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
  90
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
  91
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
  92
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
  93
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
  94
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
  95
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
  96
+
  97
+/* positioning */
  98
+.ui-icon-carat-1-n { background-position: 0 0; }
  99
+.ui-icon-carat-1-ne { background-position: -16px 0; }
  100
+.ui-icon-carat-1-e { background-position: -32px 0; }
  101
+.ui-icon-carat-1-se { background-position: -48px 0; }
  102
+.ui-icon-carat-1-s { background-position: -64px 0; }
  103
+.ui-icon-carat-1-sw { background-position: -80px 0; }
  104
+.ui-icon-carat-1-w { background-position: -96px 0; }
  105
+.ui-icon-carat-1-nw { background-position: -112px 0; }
  106
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
  107
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
  108
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
  109
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
  110
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
  111
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
  112
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
  113
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
  114
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
  115
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
  116
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
  117
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
  118
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
  119
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
  120
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
  121
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
  122
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
  123
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
  124
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
  125
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
  126
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
  127
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
  128
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
  129
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
  130
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
  131
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
  132
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
  133
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
  134
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
  135
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
  136
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
  137
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
  138
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
  139
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
  140
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
  141
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
  142
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
  143
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
  144
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
  145
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
  146
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
  147
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
  148
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
  149
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
  150
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
  151
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
  152
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
  153
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
  154
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
  155
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
  156
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
  157
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
  158
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
  159
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
  160
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
  161
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
  162
+.ui-icon-arrow-4 { background-position: 0 -80px; }
  163
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
  164
+.ui-icon-extlink { background-position: -32px -80px; }
  165
+.ui-icon-newwin { background-position: -48px -80px; }
  166
+.ui-icon-refresh { background-position: -64px -80px; }
  167
+.ui-icon-shuffle { background-position: -80px -80px; }
  168
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
  169
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
  170
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
  171
+.ui-icon-folder-open { background-position: -16px -96px; }
  172
+.ui-icon-document { background-position: -32px -96px; }
  173
+.ui-icon-document-b { background-position: -48px -96px; }
  174
+.ui-icon-note { background-position: -64px -96px; }
  175
+.ui-icon-mail-closed { background-position: -80px -96px; }
  176
+.ui-icon-mail-open { background-position: -96px -96px; }
  177
+.ui-icon-suitcase { background-position: -112px -96px; }
  178
+.ui-icon-comment { background-position: -128px -96px; }
  179
+.ui-icon-person { background-position: -144px -96px; }
  180
+.ui-icon-print { background-position: -160px -96px; }
  181
+.ui-icon-trash { background-position: -176px -96px; }
  182
+.ui-icon-locked { background-position: -192px -96px; }
  183
+.ui-icon-unlocked { background-position: -208px -96px; }
  184
+.ui-icon-bookmark { background-position: -224px -96px; }
  185
+.ui-icon-tag { background-position: -240px -96px; }
  186
+.ui-icon-home { background-position: 0 -112px; }
  187
+.ui-icon-flag { background-position: -16px -112px; }
  188
+.ui-icon-calendar { background-position: -32px -112px; }
  189
+.ui-icon-cart { background-position: -48px -112px; }
  190
+.ui-icon-pencil { background-position: -64px -112px; }
  191
+.ui-icon-clock { background-position: -80px -112px; }
  192
+.ui-icon-disk { background-position: -96px -112px; }
  193
+.ui-icon-calculator { background-position: -112px -112px; }
  194
+.ui-icon-zoomin { background-position: -128px -112px; }
  195
+.ui-icon-zoomout { background-position: -144px -112px; }
  196
+.ui-icon-search { background-position: -160px -112px; }
  197
+.ui-icon-wrench { background-position: -176px -112px; }
  198
+.ui-icon-gear { background-position: -192px -112px; }
  199
+.ui-icon-heart { background-position: -208px -112px; }
  200
+.ui-icon-star { background-position: -224px -112px; }
  201
+.ui-icon-link { background-position: -240px -112px; }
  202
+.ui-icon-cancel { background-position: 0 -128px; }
  203
+.ui-icon-plus { background-position: -16px -128px; }
  204
+.ui-icon-plusthick { background-position: -32px -128px; }
  205
+.ui-icon-minus { background-position: -48px -128px; }
  206
+.ui-icon-minusthick { background-position: -64px -128px; }
  207
+.ui-icon-close { background-position: -80px -128px; }
  208
+.ui-icon-closethick { background-position: -96px -128px; }
  209
+.ui-icon-key { background-position: -112px -128px; }
  210
+.ui-icon-lightbulb { background-position: -128px -128px; }
  211
+.ui-icon-scissors { background-position: -144px -128px; }
  212
+.ui-icon-clipboard { background-position: -160px -128px; }
  213
+.ui-icon-copy { background-position: -176px -128px; }
  214
+.ui-icon-contact { background-position: -192px -128px; }
  215
+.ui-icon-image { background-position: -208px -128px; }
  216
+.ui-icon-video { background-position: -224px -128px; }
  217
+.ui-icon-script { background-position: -240px -128px; }
  218
+.ui-icon-alert { background-position: 0 -144px; }
  219
+.ui-icon-info { background-position: -16px -144px; }
  220
+.ui-icon-notice { background-position: -32px -144px; }
  221
+.ui-icon-help { background-position: -48px -144px; }
  222
+.ui-icon-check { background-position: -64px -144px; }
  223
+.ui-icon-bullet { background-position: -80px -144px; }
  224
+.ui-icon-radio-off { background-position: -96px -144px; }
  225
+.ui-icon-radio-on { background-position: -112px -144px; }
  226
+.ui-icon-pin-w { background-position: -128px -144px; }
  227
+.ui-icon-pin-s { background-position: -144px -144px; }
  228
+.ui-icon-play { background-position: 0 -160px; }
  229
+.ui-icon-pause { background-position: -16px -160px; }
  230
+.ui-icon-seek-next { background-position: -32px -160px; }
  231
+.ui-icon-seek-prev { background-position: -48px -160px; }
  232
+.ui-icon-seek-end { background-position: -64px -160px; }
  233
+.ui-icon-seek-start { background-position: -80px -160px; }
  234
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
  235
+.ui-icon-seek-first { background-position: -80px -160px; }
  236
+.ui-icon-stop { background-position: -96px -160px; }
  237
+.ui-icon-eject { background-position: -112px -160px; }
  238
+.ui-icon-volume-off { background-position: -128px -160px; }
  239
+.ui-icon-volume-on { background-position: -144px -160px; }
  240
+.ui-icon-power { background-position: 0 -176px; }
  241
+.ui-icon-signal-diag { background-position: -16px -176px; }
  242
+.ui-icon-signal { background-position: -32px -176px; }
  243
+.ui-icon-battery-0 { background-position: -48px -176px; }
  244
+.ui-icon-battery-1 { background-position: -64px -176px; }
  245
+.ui-icon-battery-2 { background-position: -80px -176px; }
  246
+.ui-icon-battery-3 { background-position: -96px -176px; }
  247
+.ui-icon-circle-plus { background-position: 0 -192px; }
  248
+.ui-icon-circle-minus { background-position: -16px -192px; }
  249
+.ui-icon-circle-close { background-position: -32px -192px; }
  250
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
  251
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
  252
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
  253
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
  254
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
  255
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
  256
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
  257
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
  258
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
  259
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
  260
+.ui-icon-circle-check { background-position: -208px -192px; }
  261
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
  262
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
  263
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
  264
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
  265
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
  266
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
  267
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
  268
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
  269
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
  270
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
  271
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
  272
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
  273
+
  274
+
  275
+/* Misc visuals
  276
+----------------------------------*/
  277
+
  278
+/* Corner radius */
  279
+.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }
  280
+.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }
  281
+.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
  282
+.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
  283
+
  284
+/* Overlays */
  285
+.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
  286
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*!
  287
+ * jQuery UI Resizable 1.8.19
  288
+ *
  289
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
  290
+ * Dual licensed under the MIT or GPL Version 2 licenses.
  291
+ * http://jquery.org/license
  292
+ *
  293
+ * http://docs.jquery.com/UI/Resizable#theming
  294
+ */
  295
+.ui-resizable { position: relative;}
  296
+.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; }
  297
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
  298
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
  299
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
  300
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
  301
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
  302
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
  303
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
  304
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
  305
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*!
  306
+ * jQuery UI Selectable 1.8.19
  307
+ *
  308
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
  309
+ * Dual licensed under the MIT or GPL Version 2 licenses.
  310
+ * http://jquery.org/license
  311
+ *
  312
+ * http://docs.jquery.com/UI/Selectable#theming
  313
+ */
  314
+.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
  315
+/*!
  316
+ * jQuery UI Accordion 1.8.19
  317
+ *
  318
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
  319
+ * Dual licensed under the MIT or GPL Version 2 licenses.
  320
+ * http://jquery.org/license
  321
+ *
  322
+ * http://docs.jquery.com/UI/Accordion#theming
  323
+ */
  324
+/* IE/Win - Fix animation bug - #4615 */
  325
+.ui-accordion { width: 100%; }
  326
+.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
  327
+.ui-accordion .ui-accordion-li-fix { display: inline; }
  328
+.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
  329
+.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
  330
+.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
  331
+.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
  332
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
  333
+.ui-accordion .ui-accordion-content-active { display: block; }
  334
+/*!
  335
+ * jQuery UI Autocomplete 1.8.19
  336
+ *
  337
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
  338
+ * Dual licensed under the MIT or GPL Version 2 licenses.
  339
+ * http://jquery.org/license
  340
+ *
  341
+ * http://docs.jquery.com/UI/Autocomplete#theming
  342
+ */
  343
+.ui-autocomplete { position: absolute; cursor: default; }
  344
+
  345
+/* workarounds */
  346
+* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
  347
+
  348
+/*
  349
+ * jQuery UI Menu @VERSION
  350
+ *
  351
+ * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
  352
+ * Dual licensed under the MIT or GPL Version 2 licenses.
  353
+ * http://jquery.org/license
  354
+ *
  355
+ * http://docs.jquery.com/UI/Menu#theming
  356
+ */
  357
+.ui-menu {
  358
+	list-style:none;
  359
+	padding: 2px;
  360
+	margin: 0;
  361
+	display:block;
  362
+	float: left;
  363
+}
  364
+.ui-menu .ui-menu {
  365
+	margin-top: -3px;
  366
+}
  367
+.ui-menu .ui-menu-item {
  368
+	margin:0;
  369
+	padding: 0;
  370
+	zoom: 1;
  371
+	float: left;
  372
+	clear: left;
  373
+	width: 100%;
  374
+}
  375
+.ui-menu .ui-menu-item a {
  376
+	text-decoration:none;
  377
+	display:block;
  378
+	padding:.2em .4em;
  379
+	line-height:1.5;
  380
+	zoom:1;
  381
+}
  382
+.ui-menu .ui-menu-item a.ui-state-hover,
  383
+.ui-menu .ui-menu-item a.ui-state-active {
  384
+	font-weight: normal;
  385
+	margin: -1px;
  386
+}
  387
+/*!
  388
+ * jQuery UI Button 1.8.19
  389
+ *
  390
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
  391
+ * Dual licensed under the MIT or GPL Version 2 licenses.
  392
+ * http://jquery.org/license
  393
+ *
  394
+ * http://docs.jquery.com/UI/Button#theming
  395
+ */
  396
+.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
  397
+.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
  398
+button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
  399
+.ui-button-icons-only { width: 3.4em; }
  400
+button.ui-button-icons-only { width: 3.7em; }
  401
+
  402
+/*button text element */
  403
+.ui-button .ui-button-text { display: block; line-height: 1.4;  }
  404
+.ui-button-text-only .ui-button-text { padding: .4em 1em; }
  405
+.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
  406
+.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
  407
+.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
  408
+.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
  409
+/* no icon support for input elements, provide padding by default */
  410
+input.ui-button { padding: .4em 1em; }
  411
+
  412
+/*button icon element(s) */
  413
+.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
  414
+.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
  415
+.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
  416
+.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
  417
+.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
  418
+
  419
+/*button sets*/
  420
+.ui-buttonset { margin-right: 7px; }
  421
+.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
  422
+
  423
+/* workarounds */
  424
+button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
  425
+/*!
  426
+ * jQuery UI Dialog 1.8.19
  427
+ *
  428
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
  429
+ * Dual licensed under the MIT or GPL Version 2 licenses.
  430
+ * http://jquery.org/license
  431
+ *
  432
+ * http://docs.jquery.com/UI/Dialog#theming
  433
+ */
  434
+.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
  435
+.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative;  }
  436
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
  437
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
  438
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
  439
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
  440
+.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
  441
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
  442
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
  443
+.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
  444
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
  445
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
  446
+/*!
  447
+ * jQuery UI Slider 1.8.19
  448
+ *
  449
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
  450
+ * Dual licensed under the MIT or GPL Version 2 licenses.
  451
+ * http://jquery.org/license
  452
+ *
  453
+ * http://docs.jquery.com/UI/Slider#theming
  454
+ */
  455
+.ui-slider { position: relative; text-align: left; }
  456
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
  457
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
  458
+
  459
+.ui-slider-horizontal { height: .8em; }
  460
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
  461
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
  462
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
  463
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
  464
+
  465
+.ui-slider-vertical { width: .8em; height: 100px; }
  466
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
  467
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
  468
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
  469
+.ui-slider-vertical .ui-slider-range-max { top: 0; }/*!
  470
+ * jQuery UI Tabs 1.8.19
  471
+ *
  472
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
  473
+ * Dual licensed under the MIT or GPL Version 2 licenses.
  474
+ * http://jquery.org/license
  475
+ *
  476
+ * http://docs.jquery.com/UI/Tabs#theming
  477
+ */
  478
+.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
  479
+.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
  480
+.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
  481
+.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
  482
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
  483
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
  484
+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
  485
+.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
  486
+.ui-tabs .ui-tabs-hide { display: none !important; }
  487
+/*!
  488
+ * jQuery UI Datepicker 1.8.19
  489
+ *
  490
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
  491
+ * Dual licensed under the MIT or GPL Version 2 licenses.
  492
+ * http://jquery.org/license
  493
+ *
  494
+ * http://docs.jquery.com/UI/Datepicker#theming
  495
+ */
  496
+.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
  497
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
  498
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
  499
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
  500
+.ui-datepicker .ui-datepicker-prev { left:2px; }
  501
+.ui-datepicker .ui-datepicker-next { right:2px; }
  502
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
  503
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
  504
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
  505
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
  506
+.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
  507
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
  508
+.ui-datepicker select.ui-datepicker-month,
  509
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
  510
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
  511
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
  512
+.ui-datepicker td { border: 0; padding: 1px; }
  513
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
  514
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
  515
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
  516
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
  517
+
  518
+/* with multiple calendars */
  519
+.ui-datepicker.ui-datepicker-multi { width:auto; }
  520
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
  521
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
  522
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
  523
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
  524
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
  525
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
  526
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
  527
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
  528
+.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
  529
+
  530
+/* RTL support */
  531
+.ui-datepicker-rtl { direction: rtl; }
  532
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
  533
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
  534
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
  535
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
  536
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
  537
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
  538
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
  539
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
  540
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
  541
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
  542
+
  543
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
  544
+.ui-datepicker-cover {
  545
+    display: none; /*sorry for IE5*/
  546
+    display/**/: block; /*sorry for IE5*/
  547
+    position: absolute; /*must have*/
  548
+    z-index: -1; /*must have*/
  549
+    filter: mask(); /*must have*/
  550
+    top: -4px; /*must have*/
  551
+    left: -4px; /*must have*/
  552
+    width: 200px; /*must have*/
  553
+    height: 200px; /*must have*/
  554
+}/*!
  555
+ * jQuery UI Progressbar 1.8.19
  556
+ *
  557
+ * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
  558
+ * Dual licensed under the MIT or GPL Version 2 licenses.
  559
+ * http://jquery.org/license
  560
+ *
  561
+ * http://docs.jquery.com/UI/Progressbar#theming
  562
+ */
  563
+.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
  564
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
13  media/css/main.less
@@ -705,3 +705,16 @@ p.inactive {
705 705
         opacity: 0.9;
706 706
     }
707 707
 }
  708
+// Autocomplete
  709
+ul.selectable-deck {
  710
+    border-top: 1px solid rgba(0,0,0,0.1);
  711
+    width: 75%;
  712
+    margin: 5px;
  713
+    li {
  714
+        border-bottom: 1px solid rgba(0,0,0,0.1);
  715
+        overflow: hidden;
  716
+        text-overflow: ellipsis;
  717
+        background-color: white;
  718
+        padding: 3px 5px;
  719
+    }
  720
+}
125  media/js/libs/jquery-ui-1.8.19.custom.min.js
125 additions, 0 deletions not shown
37  media/selectable/css/dj.selectable.css
... ...
@@ -0,0 +1,37 @@
  1
+/*
  2
+ * django-selectable UI widget CSS
  3
+ * Source: https://bitbucket.org/mlavin/django-selectable
  4
+ * Docs: http://django-selectable.readthedocs.org/
  5
+ *
  6
+ * Copyright 2010-2012, Mark Lavin
  7
+ * BSD License
  8
+ *
  9
+*/
  10
+ul.selectable-deck, ul.ui-autocomplete {
  11
+    list-style: none outside none;
  12
+}
  13
+ul.selectable-deck li.selectable-deck-item,
  14
+ul.ui-autocomplete li.ui-menu-item {
  15
+    margin: 0;
  16
+    list-style-type: none;
  17
+}
  18
+ul.selectable-deck li.selectable-deck-item .selectable-deck-remove {
  19
+    float: right;
  20
+}
  21
+ul.selectable-deck-bottom-inline,
  22
+ul.selectable-deck-top-inline {
  23
+    padding: 0;
  24
+}
  25
+ul.selectable-deck-bottom-inline li.selectable-deck-item,
  26
+ul.selectable-deck-top-inline li.selectable-deck-item {
  27
+    display: inline;
  28
+}
  29
+ul.selectable-deck-bottom-inline li.selectable-deck-item .selectable-deck-remove,
  30
+ul.selectable-deck-top-inline li.selectable-deck-item .selectable-deck-remove {
  31
+    margin-left: 0.4em;
  32
+    display: inline;
  33
+    float: none;
  34
+}
  35
+ul.ui-autocomplete li.ui-menu-item span.highlight {
  36
+    font-weight: bold;
  37
+}
325  media/selectable/js/jquery.dj.selectable.js
... ...
@@ -0,0 +1,325 @@
  1
+/*
  2
+ * django-selectable UI widget
  3
+ * Source: https://bitbucket.org/mlavin/django-selectable
  4
+ * Docs: http://django-selectable.readthedocs.org/
  5
+ *
  6
+ * Depends:
  7
+ *   - jQuery 1.4.3+
  8
+ *   - jQuery UI 1.8 widget factory
  9
+ *
  10
+ * Copyright 2010-2012, Mark Lavin
  11
+ * BSD License
  12
+ *
  13
+*/
  14
+(function($) {
  15
+
  16
+	$.widget("ui.djselectable", {
  17
+
  18
+        options: {
  19
+            removeIcon: "ui-icon-close",
  20
+            comboboxIcon: "ui-icon-triangle-1-s",
  21
+            prepareQuery: null,
  22
+            highlightMatch: true,
  23
+            formatLabel: null
  24
+        },
  25
+
  26
+        _initDeck: function() {
  27
+            /* Create list display for currently selected items for multi-select */
  28
+            var self = this;
  29
+            var data = $(this.element).data();
  30
+            var style = data.selectablePosition || data['selectable-position'] || 'bottom';
  31
+            this.deck = $('<ul>').addClass('ui-widget selectable-deck selectable-deck-' + style);
  32
+            if (style === 'bottom' || style === 'bottom-inline') {
  33
+                $(this.element).after(this.deck);
  34
+            } else {
  35
+                $(this.element).before(this.deck);
  36
+            }
  37
+            $(self.hiddenMultipleSelector).each(function(i, input) {
  38
+                self._addDeckItem(input);
  39
+            });
  40
+        },
  41
+
  42
+        _addDeckItem: function(input) {
  43
+            /* Add new deck list item from a given hidden input */
  44
+            var self = this;
  45
+            $('<li>')
  46
+            .text($(input).attr('title'))
  47
+            .addClass('selectable-deck-item')
  48
+            .appendTo(this.deck)
  49
+            .append(
  50
+                $('<div>')
  51
+                .addClass('selectable-deck-remove')
  52
+                .append(
  53
+                    $('<a>')
  54
+                    .attr('href', '#')
  55
+                    .button({
  56
+                        icons: {
  57
+                            primary: self.options.removeIcon
  58
+                        },
  59
+                        text: false
  60
+                    })
  61
+                    .click(function() {
  62
+                        $(input).remove();
  63
+                        $(this).closest('li').remove();
  64
+                        return false;
  65
+                    })
  66
+                )
  67
+            );
  68
+        },
  69
+
  70
+        select: function(item) {
  71
+            /* Trigger selection of a given item.
  72
+            Item should contain two properties: id and value */
  73
+            var self = this,
  74
+            input = this.element;
  75
+            $(input).removeClass('ui-state-error');
  76
+            if (item) {
  77
+                if (self.allowMultiple) {
  78
+                    $(input).val("");
  79
+                    $(input).data("autocomplete").term = "";
  80
+                    if ($(self.hiddenMultipleSelector + '[value=' + item.id + ']').length === 0) {
  81
+                        var newInput = $('<input />', {
  82
+                            'type': 'hidden',
  83
+                            'name': self.hiddenName,
  84
+                            'value': item.id,
  85
+                            'title': item.value,
  86
+                            'data-selectable-type': 'hidden-multiple'
  87
+                        });
  88
+                        $(input).after(newInput);
  89
+                        self._addDeckItem(newInput);
  90
+                        return false;
  91
+                    }
  92
+                } else {
  93
+                    $(input).val(item.value);
  94
+                    var ui = {item: item};
  95
+                    $(input).trigger('autocompleteselect', [ui ]);
  96
+                }
  97
+            }
  98
+        },
  99
+
  100
+        _create: function() {
  101
+            /* Initialize a new selectable widget */
  102
+            var self = this,
  103
+            input = this.element,
  104
+            data = $(input).data();
  105
+            self.allowNew = data.selectableAllowNew || data['selectable-allow-new'];
  106
+            self.allowMultiple = data.selectableMultiple || data['selectable-multiple'];
  107
+            self.textName = $(input).attr('name');
  108
+            self.hiddenName = self.textName.replace('_0', '_1');
  109
+            self.hiddenSelector = ':input[data-selectable-type=hidden][name=' + self.hiddenName + ']';
  110
+            self.hiddenMultipleSelector = ':input[data-selectable-type=hidden-multiple][name=' + self.hiddenName + ']';
  111
+            if (self.allowMultiple) {
  112
+                self.allowNew = false;
  113
+                $(input).val("");
  114
+                this._initDeck();
  115
+            }
  116
+
  117
+            function dataSource(request, response) {
  118
+                /* Custom data source to uses the lookup url with pagination
  119
+                Adds hook for adjusting query parameters.
  120
+                Includes timestamp to prevent browser caching the lookup. */
  121
+                var url = data.selectableUrl || data['selectable-url'];
  122
+                var now = new Date().getTime();
  123
+                var query = {term: request.term, timestamp: now};
  124
+                if (self.options.prepareQuery) {
  125
+                    self.options.prepareQuery(query);
  126
+                }
  127
+                var page = $(input).data("page");
  128
+                if (page) {
  129
+                    query.page = page;
  130
+                }
  131
+				$.getJSON(url, query, response);
  132
+            }
  133
+            // Create base auto-complete lookup
  134
+            $(input).autocomplete({
  135
+                source: dataSource,
  136
+                change: function(event, ui) {
  137
+                    $(input).removeClass('ui-state-error');
  138
+                    if ($(input).val() && !ui.item) {
  139
+                        if (!self.allowNew) {
  140
+                            $(input).addClass('ui-state-error');
  141
+                        }
  142
+                    }
  143
+                    if (self.allowMultiple && !$(input).hasClass('ui-state-error')) {
  144
+                        $(input).val("");
  145
+                        $(input).data("autocomplete").term = "";
  146
+                    }
  147
+                },
  148
+                select: function(event, ui) {
  149
+                    $(input).removeClass('ui-state-error');
  150
+                    if (ui.item && ui.item.page) {
  151
+                        // Set current page value
  152
+                        $(input).data("page", ui.tem.page);
  153
+                        $('.selectable-paginator', self.menu).remove();
  154
+                        // Search for next page of results
  155
+                        $(input).autocomplete("search");
  156
+                        return false;
  157
+                    }
  158
+                    self.select(ui.item);
  159
+                }
  160
+            }).addClass("ui-widget ui-widget-content ui-corner-all");
  161
+            // Override the default auto-complete render.
  162
+            $(input).data("autocomplete")._renderItem = function(ul, item) {
  163
+                /* Adds hook for additional formatting, allows HTML in the label,
  164
+                highlights term matches and handles pagination. */
  165
+                var label = item.label;
  166
+                if (self.options.formatLabel) {
  167
+                    label = self.options.formatLabel(label, item);
  168
+                }
  169
+                if (self.options.highlightMatch) {
  170
+                    var re = new RegExp("(?![^&;]+;)(?!<[^<>]*)(" +
  171
+                    $.ui.autocomplete.escapeRegex(this.term) +
  172
+                    ")(?![^<>]*>)(?![^&;]+;)", "gi");
  173
+                    label = label.replace(re, "<span class='highlight'>$1</span>");
  174
+                }
  175
+                var li =  $("<li></li>")
  176
+                    .data("item.autocomplete", item)
  177
+                    .append($("<a></a>").append(label))
  178
+                    .appendTo(ul);
  179
+                if (item.page) {
  180
+                    li.addClass('selectable-paginator');
  181
+                }
  182
+                return li;
  183
+            };
  184
+            // Override the default auto-complete suggest.
  185
+            $(input).data("autocomplete")._suggest = function(items) {
  186
+                /* Needed for handling pagination links */
  187
+                var page = $(input).data('page');
  188
+                var ul = this.menu.element;
  189
+                if (!page) {
  190
+                    ul.empty();
  191
+                }
  192
+                $(input).data('page', null);
  193
+                ul.zIndex(this.element.zIndex() + 1);
  194
+                this._renderMenu(ul, items);
  195
+                this.menu.deactivate();
  196
+                this.menu.refresh();
  197
+                // size and position menu
  198
+                ul.show();
  199
+                this._resizeMenu();
  200
+                ul.position($.extend({of: this.element}, this.options.position));
  201
+                if (this.options.autoFocus) {
  202
+                    this.menu.next(new $.Event("mouseover"));
  203
+                }
  204
+            };
  205
+            // Additional work for combobox widgets
  206
+            var selectableType = data.selectableType || data['selectable-type'];
  207
+            if (selectableType === 'combobox') {
  208
+                // Change auto-complete options
  209
+                $(input).autocomplete("option", {
  210
+                    delay: 0,
  211
+                    minLength: 0
  212
+                })
  213
+                .removeClass("ui-corner-all")
  214
+                .addClass("ui-corner-left ui-combo-input");
  215
+                // Add show all items button
  216
+                $("<button>&nbsp;</button>").attr("tabIndex", -1).attr("title", "Show All Items")
  217
+                .insertAfter($(input))
  218
+                .button({
  219
+                    icons: {
  220
+                        primary: self.options.comboboxIcon
  221
+                    },
  222
+                    text: false
  223
+                })
  224
+                .removeClass("ui-corner-all")
  225
+                .addClass("ui-corner-right ui-button-icon ui-combo-button")
  226
+                .click(function() {
  227
+                    // close if already visible
  228
+                    if ($(input).autocomplete("widget").is(":visible")) {
  229
+                        $(input).autocomplete("close");
  230
+                        return false;
  231
+                    }
  232
+                    // pass empty string as value to search for, displaying all results
  233
+                    $(input).autocomplete("search", "");
  234
+                    $(input).focus();
  235
+                    return false;
  236
+                });
  237
+            }
  238
+        }
  239
+	});
  240
+})(jQuery);
  241
+
  242
+function bindSelectables(context) {
  243
+    /* Bind all selectable widgets in a given context.
  244
+    Automatically called on document.ready.
  245
+    Additional calls can be made for dynamically added widgets.
  246
+    */
  247
+    $(":input[data-selectable-type=text]", context).djselectable();
  248
+    $(":input[data-selectable-type=combobox]", context).djselectable();
  249
+    $(":input[data-selectable-type=hidden]", context).each(function(i, elem) {
  250
+        var hiddenName = $(elem).attr('name');
  251
+        var textName = hiddenName.replace('_1', '_0');
  252
+        $(":input[name=" + textName + "][data-selectable-url]").bind(
  253
+            "autocompletechange autocompleteselect",
  254
+            function(event, ui) {
  255
+                if (ui.item && ui.item.id) {
  256
+                    $(elem).val(ui.item.id);
  257
+                } else {
  258
+                    $(elem).val("");
  259
+                }
  260
+            }
  261
+        );
  262
+    });
  263
+}
  264
+
  265
+/* Monkey-patch Django's dynamic formset, if defined */
  266
+if (typeof(django) !== "undefined" && typeof(django.jQuery) !== "undefined") {
  267
+    if (django.jQuery.fn.formset) {
  268
+        var oldformset = django.jQuery.fn.formset;
  269
+        django.jQuery.fn.formset = function(opts) {
  270
+            var options = $.extend({}, opts);
  271
+            var addedevent = function(row) {
  272
+                bindSelectables($(row));
  273
+            };
  274
+            var added = null;
  275
+            if (options.added) {
  276
+                // Wrap previous added function and include call to bindSelectables
  277
+                var oldadded = options.added;
  278
+                added = function(row) { oldadded(row); addedevent(row); };
  279
+            }
  280
+            options.added = added || addedevent;
  281
+            return oldformset.call(this, options);
  282
+        };
  283
+    }
  284
+}