浏览代码

Merge branch 'dev'

Denis K 9 年之前
父节点
当前提交
6e0d2e77dd
共有 55 个文件被更改,包括 3802 次插入252 次删除
  1. 10 0
      CHANGELOG.rst
  2. 46 0
      README.rst
  3. 2 2
      docs/config_file.rst
  4. 1 0
      docs/getting_started.rst
  5. 1 4
      docs/index.rst
  6. 5 0
      docs/install.rst
  7. 45 0
      docs/install_dashboard.rst
  8. 1 1
      jet/__init__.py
  9. 0 8
      jet/dashboard/dashboard.py
  10. 2 2
      jet/dashboard/dashboard_modules/google_analytics.py
  11. 2 2
      jet/dashboard/dashboard_modules/yandex_metrika.py
  12. 28 0
      jet/dashboard/forms.py
  13. 8 0
      jet/dashboard/templates/jet.dashboard/dashboard_tools.html
  14. 6 2
      jet/dashboard/templatetags/jet_dashboard_tags.py
  15. 1 1
      jet/dashboard/urls.py
  16. 11 8
      jet/dashboard/views.py
  17. 二进制
      jet/locale/en/LC_MESSAGES/django.mo
  18. 60 51
      jet/locale/en/LC_MESSAGES/django.po
  19. 二进制
      jet/locale/en/LC_MESSAGES/djangojs.mo
  20. 16 9
      jet/locale/en/LC_MESSAGES/djangojs.po
  21. 二进制
      jet/locale/ru/LC_MESSAGES/django.mo
  22. 60 51
      jet/locale/ru/LC_MESSAGES/django.po
  23. 二进制
      jet/locale/ru/LC_MESSAGES/djangojs.mo
  24. 16 9
      jet/locale/ru/LC_MESSAGES/djangojs.po
  25. 2 0
      jet/static/jet/css/_changelist.scss
  26. 21 1
      jet/static/jet/css/_content.scss
  27. 6 0
      jet/static/jet/css/_forms.scss
  28. 26 2
      jet/static/jet/css/_sidebar.scss
  29. 0 20
      jet/static/jet/css/_table.scss
  30. 1 0
      jet/static/jet/css/icons/_variables.scss
  31. 二进制
      jet/static/jet/css/icons/fonts/jet-icons.eot
  32. 1 0
      jet/static/jet/css/icons/fonts/jet-icons.svg
  33. 二进制
      jet/static/jet/css/icons/fonts/jet-icons.ttf
  34. 二进制
      jet/static/jet/css/icons/fonts/jet-icons.woff
  35. 8 5
      jet/static/jet/css/icons/style.css
  36. 50 26
      jet/static/jet/css/themes/default/base.css
  37. 0 0
      jet/static/jet/css/themes/default/base.css.map
  38. 0 0
      jet/static/jet/css/themes/default/jquery-ui.theme.css.map
  39. 0 0
      jet/static/jet/css/themes/default/select2.theme.css.map
  40. 50 26
      jet/static/jet/css/themes/green/base.css
  41. 0 0
      jet/static/jet/css/themes/green/base.css.map
  42. 0 0
      jet/static/jet/css/themes/green/jquery-ui.theme.css.map
  43. 0 0
      jet/static/jet/css/themes/green/select2.theme.css.map
  44. 43 0
      jet/static/jet/js/main.js
  45. 0 0
      jet/static/jet/js/main.min.js
  46. 108 0
      jet/static/jet/vendor/perfect-scrollbar/css/perfect-scrollbar.css
  47. 7 0
      jet/static/jet/vendor/perfect-scrollbar/css/perfect-scrollbar.css.map
  48. 149 0
      jet/static/jet/vendor/perfect-scrollbar/css/perfect-scrollbar.scss
  49. 1492 0
      jet/static/jet/vendor/perfect-scrollbar/js/perfect-scrollbar.jquery.js
  50. 1 0
      jet/static/jet/vendor/perfect-scrollbar/js/perfect-scrollbar.jquery.min.js
  51. 1463 0
      jet/static/jet/vendor/perfect-scrollbar/js/perfect-scrollbar.js
  52. 1 0
      jet/static/jet/vendor/perfect-scrollbar/js/perfect-scrollbar.min.js
  53. 34 20
      jet/templates/admin/base.html
  54. 2 2
      jet/templates/admin/search_form.html
  55. 16 0
      jet/tests/test_views.py

+ 10 - 0
CHANGELOG.rst

@@ -1,6 +1,16 @@
 Changelog
 =========
 
+0.0.9
+-----
+* [Feature] Replace sidemenu scrollbars with Mac-like ones
+* [Feature] Added dashboard reset button
+* [Feature] Updated sidebar links ui
+* [Fix] Fixed filter submit block text alignment
+* [Fix] Made boolean field icon style global
+* [Fix] Fixed metrics requests timezone to be TIME_ZONE from settings
+
+
 0.0.8
 -----
 * Change license to GPLv2

+ 46 - 0
README.rst

@@ -111,3 +111,49 @@ Installation
         
 * Clear your browser cache
 
+Dashboard installation
+======================
+
+.. note:: Dashboard is located into a separate application. So after a typical JET installation it won't be active.
+          To enable dashboard application follow these steps:
+
+* Add 'jet.dashboard' application to the INSTALLED_APPS setting of your Django project settings.py file (note it should be before 'jet'):
+
+.. code:: python
+
+    INSTALLED_APPS = (
+        ...
+        'jet.dashboard',
+        'jet',
+        'django.contrib.admin',
+        ...
+    )
+
+* Add URL-pattern to the urlpatterns of your Django project urls.py file (they are needed for related–lookups and autocompletes):
+
+.. code:: python
+
+    urlpatterns = patterns(
+        '',
+        url(r'^jet/', include('jet.urls', 'jet')),  # Django JET URLS
+        url(r'^jet/dashboard/', include('jet.dashboard.urls', 'jet-dashboard')),  # Django JET dashboard URLS
+        url(r'^admin/', include(admin.site.urls)),
+        ...
+    )
+
+* Create database tables:
+
+.. code:: python
+
+    python manage.py migrate dashboard
+    # or
+    python manage.py syncdb
+
+* Collect static if you are in production environment:
+
+.. code:: python
+
+        python manage.py collectstatic
+
+
+

+ 2 - 2
docs/config_file.rst

@@ -34,8 +34,8 @@ to start using your own theme.
 JET_INDEX_DASHBOARD
 -------------------
 
-Sets which dashboard class will be used for rending admin index dashboard. Allows you to create
-your own dashboard with custom modules with pre-installed layout.
+Sets which dashboard class will be used for rendering admin index dashboard. Allows you to create
+your own dashboard with custom modules and pre-installed layout.
 
 .. code:: python
 

+ 1 - 0
docs/getting_started.rst

@@ -8,3 +8,4 @@ Contents:
    :maxdepth: 2
 
    install
+   install_dashboard

+ 1 - 4
docs/index.rst

@@ -83,8 +83,5 @@ Changeform + sidemenu
 License
 =======
 Django JET is licensed under a
-Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License
-
-See online version of this license here:
-https://creativecommons.org/licenses/by-nc-sa/4.0/
+The GNU General Public License, Version 2
 

+ 5 - 0
docs/install.rst

@@ -2,6 +2,10 @@
 Installation
 ============
 
+.. note:: After following this instruction Django JET dashboard won't be active (as it is located into
+          a separate application). If you want to make it work, you will have to enable dashboard application
+          by following :doc:`install_dashboard` steps too.
+
 * Download and install latest version of Django JET:
 
 .. code:: python
@@ -18,6 +22,7 @@ Installation
         ...
         'jet',
         'django.contrib.admin',
+        ...
     )
 
 * Make sure 'django.core.context_processors.request' context processor is enabled in settings.py:

+ 45 - 0
docs/install_dashboard.rst

@@ -0,0 +1,45 @@
+======================
+Dashboard installation
+======================
+
+.. note:: Dashboard is located into a separate application. So after a typical JET installation it won't be active.
+          To enable dashboard application follow these steps:
+
+* Add 'jet.dashboard' application to the INSTALLED_APPS setting of your Django project settings.py file (note it should be before 'jet'):
+
+.. code:: python
+
+    INSTALLED_APPS = (
+        ...
+        'jet.dashboard',
+        'jet',
+        'django.contrib.admin',
+        ...
+    )
+
+* Add URL-pattern to the urlpatterns of your Django project urls.py file (they are needed for related–lookups and autocompletes):
+
+.. code:: python
+
+    urlpatterns = patterns(
+        '',
+        url(r'^jet/', include('jet.urls', 'jet')),  # Django JET URLS
+        url(r'^jet/dashboard/', include('jet.dashboard.urls', 'jet-dashboard')),  # Django JET dashboard URLS
+        url(r'^admin/', include(admin.site.urls)),
+        ...
+    )
+
+* Create database tables:
+
+.. code:: python
+
+    python manage.py migrate dashboard
+    # or
+    python manage.py syncdb
+
+* Collect static if you are in production environment:
+
+.. code:: python
+
+        python manage.py collectstatic
+

+ 1 - 1
jet/__init__.py

@@ -1 +1 @@
-VERSION = '0.0.8'
+VERSION = '0.0.9'

+ 0 - 8
jet/dashboard/dashboard.py

@@ -31,7 +31,6 @@ class Dashboard(object):
 
     def set_context(self, context):
         self.context = context
-        self.update_app_label()
         self.init_with_context(context)
         self.load_modules()
 
@@ -45,9 +44,6 @@ class Dashboard(object):
 
         return module
 
-    def update_app_label(self):
-        pass
-
     def create_initial_module_models(self, user):
         module_models = []
 
@@ -135,10 +131,6 @@ class Dashboard(object):
 
 
 class AppIndexDashboard(Dashboard):
-    def update_app_label(self):
-        resolver = resolve(self.context['request'].path)
-        self.app_label = resolver.kwargs.get('app_label')
-
     def get_app_content_types(self):
         return self.app_label + '.*',
 

+ 2 - 2
jet/dashboard/dashboard_modules/google_analytics.py

@@ -282,8 +282,8 @@ class GoogleAnalyticsBase(DashboardModule):
 
     def api_ga(self, group=None):
         if self.counter_attached():
-            date1 = datetime.datetime.utcnow() - datetime.timedelta(days=self.period)
-            date2 = datetime.datetime.utcnow()
+            date1 = datetime.datetime.now() - datetime.timedelta(days=self.period)
+            date2 = datetime.datetime.now()
 
             try:
                 client = GoogleAnalyticsClient(self.storage)

+ 2 - 2
jet/dashboard/dashboard_modules/yandex_metrika.py

@@ -224,8 +224,8 @@ class YandexMetrikaBase(DashboardModule):
 
     def api_stat_traffic_summary(self, group=None):
         if self.counter_attached():
-            date1 = datetime.datetime.utcnow() - datetime.timedelta(days=self.period)
-            date2 = datetime.datetime.utcnow()
+            date1 = datetime.datetime.now() - datetime.timedelta(days=self.period)
+            date2 = datetime.datetime.now()
 
             client = YandexMetrikaClient(self.access_token)
             result, exception = client.api_stat_traffic_summary(self.counter, date1, date2, group)

+ 28 - 0
jet/dashboard/forms.py

@@ -130,3 +130,31 @@ class RemoveDashboardModuleForm(forms.ModelForm):
     def save(self, commit=True):
         if commit:
             self.instance.delete()
+
+
+class ResetDashboardForm(forms.Form):
+    app_label = forms.CharField(required=False)
+
+    def __init__(self, request, *args, **kwargs):
+        self.request = request
+        super(ResetDashboardForm, self).__init__(*args, **kwargs)
+
+    class Meta:
+        model = UserDashboardModule
+        fields = []
+
+    def clean(self):
+        data = super(ResetDashboardForm, self).clean()
+        data['app_label'] = data['app_label'] if data['app_label'] else None
+
+        if not self.request.user.is_authenticated():
+            raise ValidationError('error')
+
+        return data
+
+    def save(self, commit=True):
+        if commit:
+            UserDashboardModule.objects.filter(
+                user=self.request.user.pk,
+                app_label=self.cleaned_data['app_label']
+            ).delete()

+ 8 - 0
jet/dashboard/templates/jet.dashboard/dashboard_tools.html

@@ -18,6 +18,14 @@
         </select><a href="#" class="button button-secondary add-dashboard-link" title="{% trans "Add" %}"><span class="icon-add"></span></a>
         <input type="hidden" name="app_label" value="{% if app_label %}{{ app_label }}{% endif %}">
         <input type="hidden" name="type" value="">
+        <a href="#" class="button button-transparent reset-dashboard-link" title="{% trans "Reset widgets" %}"><span class="icon-reset"></span></a>
     </form>
+    <form action="{% url "jet-dashboard:reset_dashboard" %}" method="POST" id="reset-dashboard-form">
+        {% csrf_token %}
+        <input type="hidden" name="app_label" value="{% if app_label %}{{ app_label }}{% endif %}">
+    </form>
+    <div class="dialog-confirm" id="reset-dashboard-dialog" title="{% trans "Reset widgets" %}">
+        <p>{% trans "Are you sure want to reset widgets?" %}</p>
+    </div>
 </div>
 

+ 6 - 2
jet/dashboard/templatetags/jet_dashboard_tags.py

@@ -1,5 +1,6 @@
 from __future__ import unicode_literals
 from django import template
+from django.core.urlresolvers import resolve
 from jet.dashboard.utils import get_current_dashboard
 
 register = template.Library()
@@ -8,5 +9,8 @@ register = template.Library()
 @register.assignment_tag(takes_context=True)
 def get_dashboard(context, location):
     dashboard_cls = get_current_dashboard(location)
-    dashboard = dashboard_cls(context)
-    return dashboard
+
+    resolver = resolve(context['request'].path)
+    app_label = resolver.kwargs.get('app_label')
+
+    return dashboard_cls(context, app_label=app_label)

+ 1 - 1
jet/dashboard/urls.py

@@ -38,7 +38,7 @@ urlpatterns = patterns(
         name='load_dashboard_module'
     ),
     url(
-        r'^reset_dashboard/((?P<app_label>[^/]+)/)?$',
+        r'^reset_dashboard/$',
         reset_dashboard_view,
         name='reset_dashboard'
     ),

+ 11 - 8
jet/dashboard/views.py

@@ -1,10 +1,9 @@
 from django.contrib import messages
 from django.core.urlresolvers import reverse
 from django.forms.formsets import formset_factory
-from django.shortcuts import redirect
 from django.views.decorators.http import require_POST, require_GET
 from jet.dashboard.forms import UpdateDashboardModulesForm, AddUserDashboardModuleForm, \
-    UpdateDashboardModuleCollapseForm, RemoveDashboardModuleForm
+    UpdateDashboardModuleCollapseForm, RemoveDashboardModuleForm, ResetDashboardForm
 from jet.dashboard.models import UserDashboardModule
 from jet.utils import JsonResponse, get_app_list, SuccessMessageMixin
 from django.views.generic import UpdateView
@@ -214,10 +213,14 @@ def load_dashboard_module_view(request, pk):
     return JsonResponse(result)
 
 
-def reset_dashboard_view(request, app_label=None):
-    UserDashboardModule.objects.filter(user=request.user.pk, app_label=app_label).delete()
-    if app_label:
-        url = reverse('admin:app_list', kwargs={'app_label': app_label})
+@require_POST
+def reset_dashboard_view(request):
+    result = {'error': False}
+    form = ResetDashboardForm(request, request.POST)
+
+    if form.is_valid():
+        form.save()
     else:
-        url = reverse('admin:index')
-    return redirect(url)
+        result['error'] = True
+
+    return JsonResponse(result)

二进制
jet/locale/en/LC_MESSAGES/django.mo


+ 60 - 51
jet/locale/en/LC_MESSAGES/django.po

@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-09-07 13:42+0000\n"
+"POT-Creation-Date: 2015-09-11 12:45+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -23,16 +23,16 @@ msgstr ""
 msgid "Return to site"
 msgstr ""
 
-#: dashboard/dashboard.py:166 templates/admin/base.html:77
+#: dashboard/dashboard.py:166 templates/admin/base.html:80
 msgid "Change password"
 msgstr ""
 
-#: dashboard/dashboard.py:168 templates/admin/base.html:81
+#: dashboard/dashboard.py:168 templates/admin/base.html:84
 msgid "Log out"
 msgstr ""
 
 #: dashboard/dashboard.py:176 dashboard/modules.py:160
-#: templates/admin/base.html:157 templates/admin/index.html:14
+#: templates/admin/base.html:160 templates/admin/index.html:14
 msgid "Applications"
 msgstr ""
 
@@ -80,62 +80,62 @@ msgid "Grant access"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:161
-#: dashboard/dashboard_modules/yandex_metrika.py:113
+#: dashboard/dashboard_modules/yandex_metrika.py:116
 msgid "Access"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:162
-#: dashboard/dashboard_modules/yandex_metrika.py:114
+#: dashboard/dashboard_modules/yandex_metrika.py:117
 msgid "Counter"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:163
-#: dashboard/dashboard_modules/yandex_metrika.py:115
+#: dashboard/dashboard_modules/yandex_metrika.py:118
 msgid "Statistics period"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:164
-#: dashboard/dashboard_modules/yandex_metrika.py:116
+#: dashboard/dashboard_modules/yandex_metrika.py:119
 msgid "Today"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:165
-#: dashboard/dashboard_modules/yandex_metrika.py:117
+#: dashboard/dashboard_modules/yandex_metrika.py:120
 msgid "Last week"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:166
-#: dashboard/dashboard_modules/yandex_metrika.py:118
+#: dashboard/dashboard_modules/yandex_metrika.py:121
 msgid "Last month"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:167
-#: dashboard/dashboard_modules/yandex_metrika.py:119
+#: dashboard/dashboard_modules/yandex_metrika.py:122
 msgid "Last quarter"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:168
-#: dashboard/dashboard_modules/yandex_metrika.py:120
+#: dashboard/dashboard_modules/yandex_metrika.py:123
 msgid "Last year"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:178
-#: dashboard/dashboard_modules/yandex_metrika.py:130
+#: dashboard/dashboard_modules/yandex_metrika.py:133
 msgid "none"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:181
-#: dashboard/dashboard_modules/yandex_metrika.py:133
+#: dashboard/dashboard_modules/yandex_metrika.py:136
 msgid "grant access first"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:181
-#: dashboard/dashboard_modules/yandex_metrika.py:133
+#: dashboard/dashboard_modules/yandex_metrika.py:136
 msgid "counters loading failed"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:186
-#: dashboard/dashboard_modules/yandex_metrika.py:138
+#: dashboard/dashboard_modules/yandex_metrika.py:141
 msgid "Show"
 msgstr ""
 
@@ -150,7 +150,7 @@ msgid "Sessions"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:189
-#: dashboard/dashboard_modules/yandex_metrika.py:141
+#: dashboard/dashboard_modules/yandex_metrika.py:144
 #: dashboard/templates/jet.dashboard/modules/google_analytics_period_visitors.html:17
 #: dashboard/templates/jet.dashboard/modules/yandex_metrika_period_visitors.html:17
 msgid "Views"
@@ -158,29 +158,29 @@ msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:191
 #: dashboard/dashboard_modules/google_analytics.py:199
-#: dashboard/dashboard_modules/yandex_metrika.py:143
-#: dashboard/dashboard_modules/yandex_metrika.py:151
+#: dashboard/dashboard_modules/yandex_metrika.py:146
+#: dashboard/dashboard_modules/yandex_metrika.py:154
 msgid "Group"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:192
 #: dashboard/dashboard_modules/google_analytics.py:200
-#: dashboard/dashboard_modules/yandex_metrika.py:144
-#: dashboard/dashboard_modules/yandex_metrika.py:152
+#: dashboard/dashboard_modules/yandex_metrika.py:147
+#: dashboard/dashboard_modules/yandex_metrika.py:155
 msgid "By day"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:193
 #: dashboard/dashboard_modules/google_analytics.py:201
-#: dashboard/dashboard_modules/yandex_metrika.py:145
-#: dashboard/dashboard_modules/yandex_metrika.py:153
+#: dashboard/dashboard_modules/yandex_metrika.py:148
+#: dashboard/dashboard_modules/yandex_metrika.py:156
 msgid "By week"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:194
 #: dashboard/dashboard_modules/google_analytics.py:202
-#: dashboard/dashboard_modules/yandex_metrika.py:146
-#: dashboard/dashboard_modules/yandex_metrika.py:154
+#: dashboard/dashboard_modules/yandex_metrika.py:149
+#: dashboard/dashboard_modules/yandex_metrika.py:157
 msgid "By month"
 msgstr ""
 
@@ -200,13 +200,13 @@ msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:297
 #: dashboard/dashboard_modules/google_analytics_views.py:42
-#: dashboard/dashboard_modules/yandex_metrika.py:231
+#: dashboard/dashboard_modules/yandex_metrika.py:234
 #: dashboard/dashboard_modules/yandex_metrika_views.py:37
 msgid "API request failed."
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:299
-#: dashboard/dashboard_modules/yandex_metrika.py:233
+#: dashboard/dashboard_modules/yandex_metrika.py:236
 #, python-format
 msgid " Try to <a href=\"%s\">revoke and grant access</a> again"
 msgstr ""
@@ -224,16 +224,16 @@ msgid "sessions"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:318
-#: dashboard/dashboard_modules/yandex_metrika.py:254
+#: dashboard/dashboard_modules/yandex_metrika.py:257
 msgid "views"
 msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:320
 #: dashboard/dashboard_modules/google_analytics.py:365
 #: dashboard/dashboard_modules/google_analytics.py:404
-#: dashboard/dashboard_modules/yandex_metrika.py:256
-#: dashboard/dashboard_modules/yandex_metrika.py:295
-#: dashboard/dashboard_modules/yandex_metrika.py:328
+#: dashboard/dashboard_modules/yandex_metrika.py:259
+#: dashboard/dashboard_modules/yandex_metrika.py:298
+#: dashboard/dashboard_modules/yandex_metrika.py:331
 msgid "Bad server response"
 msgstr ""
 
@@ -257,51 +257,51 @@ msgstr ""
 msgid "Bad arguments"
 msgstr ""
 
-#: dashboard/dashboard_modules/yandex_metrika.py:139
+#: dashboard/dashboard_modules/yandex_metrika.py:142
 #: dashboard/templates/jet.dashboard/modules/yandex_metrika_period_visitors.html:15
 msgid "Visitors"
 msgstr ""
 
-#: dashboard/dashboard_modules/yandex_metrika.py:140
+#: dashboard/dashboard_modules/yandex_metrika.py:143
 #: dashboard/templates/jet.dashboard/modules/yandex_metrika_period_visitors.html:16
 msgid "Visits"
 msgstr ""
 
-#: dashboard/dashboard_modules/yandex_metrika.py:214
+#: dashboard/dashboard_modules/yandex_metrika.py:217
 #, python-format
 msgid ""
 "Please <a href=\"%s\">attach Yandex account and choose Yandex Metrika "
 "counter</a> to start using widget"
 msgstr ""
 
-#: dashboard/dashboard_modules/yandex_metrika.py:217
+#: dashboard/dashboard_modules/yandex_metrika.py:220
 #, python-format
 msgid ""
 "Please <a href=\"%s\">select Yandex Metrika counter</a> to start using widget"
 msgstr ""
 
-#: dashboard/dashboard_modules/yandex_metrika.py:240
+#: dashboard/dashboard_modules/yandex_metrika.py:243
 msgid "Yandex Metrika visitors totals"
 msgstr ""
 
-#: dashboard/dashboard_modules/yandex_metrika.py:252
+#: dashboard/dashboard_modules/yandex_metrika.py:255
 msgid "visitors"
 msgstr ""
 
-#: dashboard/dashboard_modules/yandex_metrika.py:253
+#: dashboard/dashboard_modules/yandex_metrika.py:256
 msgid "visits"
 msgstr ""
 
-#: dashboard/dashboard_modules/yandex_metrika.py:260
+#: dashboard/dashboard_modules/yandex_metrika.py:263
 msgid "Yandex Metrika visitors chart"
 msgstr ""
 
-#: dashboard/dashboard_modules/yandex_metrika.py:299
+#: dashboard/dashboard_modules/yandex_metrika.py:302
 msgid "Yandex Metrika period visitors"
 msgstr ""
 
 #: dashboard/models.py:11 dashboard/modules.py:116
-#: templates/admin/base.html:189
+#: templates/admin/base.html:192
 msgid "Title"
 msgstr ""
 
@@ -345,7 +345,7 @@ msgstr ""
 msgid "user dashboard modules"
 msgstr ""
 
-#: dashboard/modules.py:115 models.py:12 templates/admin/base.html:191
+#: dashboard/modules.py:115 models.py:12 templates/admin/base.html:194
 msgid "URL"
 msgstr ""
 
@@ -399,7 +399,7 @@ msgstr ""
 
 #: dashboard/templates/admin/app_index.html:32
 #: dashboard/templates/jet.dashboard/update_module.html:14
-#: templates/admin/base.html:92 templates/admin/base.html.py:141
+#: templates/admin/base.html:95 templates/admin/base.html.py:144
 #: templates/admin/change_form.html:17 templates/admin/change_list.html:33
 #: templates/admin/delete_confirmation.html:8
 #: templates/admin/delete_selected_confirmation.html:8
@@ -437,6 +437,15 @@ msgstr ""
 msgid "Add"
 msgstr ""
 
+#: dashboard/templates/jet.dashboard/dashboard_tools.html:21
+#: dashboard/templates/jet.dashboard/dashboard_tools.html:27
+msgid "Reset widgets"
+msgstr ""
+
+#: dashboard/templates/jet.dashboard/dashboard_tools.html:28
+msgid "Are you sure want to reset widgets?"
+msgstr ""
+
 #: dashboard/templates/jet.dashboard/module.html:19
 #: dashboard/templates/jet.dashboard/modules/app_list.html:24
 #: dashboard/templates/jet.dashboard/modules/model_list.html:14
@@ -500,7 +509,7 @@ msgid "Please correct the errors below."
 msgstr ""
 
 #: dashboard/templates/jet.dashboard/update_module.html:126
-#: templates/admin/base.html:211 templates/admin/base.html.py:218
+#: templates/admin/base.html:214 templates/admin/base.html.py:221
 #: templates/admin/edit_inline/stacked.html:21
 #: templates/admin/edit_inline/stacked.html:75
 #: templates/admin/edit_inline/tabular.html:100
@@ -543,7 +552,7 @@ msgstr ""
 msgid "bookmark"
 msgstr ""
 
-#: models.py:19 templates/admin/base.html:204
+#: models.py:19 templates/admin/base.html:207
 msgid "bookmarks"
 msgstr ""
 
@@ -576,27 +585,27 @@ msgstr ""
 msgid "Clear selection"
 msgstr ""
 
-#: templates/admin/base.html:146
+#: templates/admin/base.html:149
 msgid "View site"
 msgstr ""
 
-#: templates/admin/base.html:186 templates/admin/base.html.py:203
+#: templates/admin/base.html:189 templates/admin/base.html.py:206
 msgid "Add bookmark"
 msgstr ""
 
-#: templates/admin/base.html:199
+#: templates/admin/base.html:202
 msgid "Delete bookmark"
 msgstr ""
 
-#: templates/admin/base.html:200
+#: templates/admin/base.html:203
 msgid "Are you sure want to delete this bookmark?"
 msgstr ""
 
-#: templates/admin/base.html:226
+#: templates/admin/base.html:229
 msgid "Documentation"
 msgstr ""
 
-#: templates/admin/base.html:249
+#: templates/admin/base.html:252
 msgid "Application page"
 msgstr ""
 

二进制
jet/locale/en/LC_MESSAGES/djangojs.mo


+ 16 - 9
jet/locale/en/LC_MESSAGES/djangojs.po

@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-08-07 13:32+0000\n"
+"POT-Creation-Date: 2015-09-11 12:44+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -15,36 +15,43 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: static/jet/js/main.js:266
+#: static/jet/js/main.js:266 static/jet/js/main.min.js:1
 msgid "Add"
 msgstr ""
 
 #: static/jet/js/main.js:271 static/jet/js/main.js:315
-#: static/jet/js/main.js:721
+#: static/jet/js/main.js:766 static/jet/js/main.js:862
+#: static/jet/js/main.min.js:1 static/jet/js/main.min.js:2
+#: static/jet/js/main.min.js:3
 msgid "Cancel"
 msgstr ""
 
-#: static/jet/js/main.js:310 static/jet/js/main.js:716
+#: static/jet/js/main.js:310 static/jet/js/main.js:761
+#: static/jet/js/main.min.js:1 static/jet/js/main.min.js:2
 msgid "Delete"
 msgstr ""
 
-#: static/jet/js/main.js:336
+#: static/jet/js/main.js:336 static/jet/js/main.min.js:1
 msgid "Hide applications"
 msgstr ""
 
-#: static/jet/js/main.js:338
+#: static/jet/js/main.js:338 static/jet/js/main.min.js:1
 msgid "Show hidden"
 msgstr ""
 
-#: static/jet/js/main.js:792
+#: static/jet/js/main.js:857 static/jet/js/main.min.js:3
+msgid "Yes"
+msgstr ""
+
+#: static/jet/js/main.js:884 static/jet/js/main.min.js:3
 msgid "Warning: you have unsaved changes"
 msgstr ""
 
-#: static/jet/js/select2.jet.js:108
+#: static/jet/js/select2.jet.js:108 static/jet/js/select2.jet.min.js:1
 msgid "select all"
 msgstr ""
 
-#: static/jet/js/select2.jet.js:111
+#: static/jet/js/select2.jet.js:111 static/jet/js/select2.jet.min.js:1
 msgid "deselect all"
 msgstr ""
 

二进制
jet/locale/ru/LC_MESSAGES/django.mo


+ 60 - 51
jet/locale/ru/LC_MESSAGES/django.po

@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-09-07 13:42+0000\n"
+"POT-Creation-Date: 2015-09-11 12:45+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -25,16 +25,16 @@ msgstr "Быстрые ссылки"
 msgid "Return to site"
 msgstr "Вернуться на сайт"
 
-#: dashboard/dashboard.py:166 templates/admin/base.html:77
+#: dashboard/dashboard.py:166 templates/admin/base.html:80
 msgid "Change password"
 msgstr ""
 
-#: dashboard/dashboard.py:168 templates/admin/base.html:81
+#: dashboard/dashboard.py:168 templates/admin/base.html:84
 msgid "Log out"
 msgstr ""
 
 #: dashboard/dashboard.py:176 dashboard/modules.py:160
-#: templates/admin/base.html:157 templates/admin/index.html:14
+#: templates/admin/base.html:160 templates/admin/index.html:14
 msgid "Applications"
 msgstr "Приложения"
 
@@ -82,62 +82,62 @@ msgid "Grant access"
 msgstr "Предоставить доступ"
 
 #: dashboard/dashboard_modules/google_analytics.py:161
-#: dashboard/dashboard_modules/yandex_metrika.py:113
+#: dashboard/dashboard_modules/yandex_metrika.py:116
 msgid "Access"
 msgstr "Доступ"
 
 #: dashboard/dashboard_modules/google_analytics.py:162
-#: dashboard/dashboard_modules/yandex_metrika.py:114
+#: dashboard/dashboard_modules/yandex_metrika.py:117
 msgid "Counter"
 msgstr "Счетчик"
 
 #: dashboard/dashboard_modules/google_analytics.py:163
-#: dashboard/dashboard_modules/yandex_metrika.py:115
+#: dashboard/dashboard_modules/yandex_metrika.py:118
 msgid "Statistics period"
 msgstr "Статистика за период"
 
 #: dashboard/dashboard_modules/google_analytics.py:164
-#: dashboard/dashboard_modules/yandex_metrika.py:116
+#: dashboard/dashboard_modules/yandex_metrika.py:119
 msgid "Today"
 msgstr "Сегодня"
 
 #: dashboard/dashboard_modules/google_analytics.py:165
-#: dashboard/dashboard_modules/yandex_metrika.py:117
+#: dashboard/dashboard_modules/yandex_metrika.py:120
 msgid "Last week"
 msgstr "Последняя неделя"
 
 #: dashboard/dashboard_modules/google_analytics.py:166
-#: dashboard/dashboard_modules/yandex_metrika.py:118
+#: dashboard/dashboard_modules/yandex_metrika.py:121
 msgid "Last month"
 msgstr "Последний месяц"
 
 #: dashboard/dashboard_modules/google_analytics.py:167
-#: dashboard/dashboard_modules/yandex_metrika.py:119
+#: dashboard/dashboard_modules/yandex_metrika.py:122
 msgid "Last quarter"
 msgstr "Последний квартал"
 
 #: dashboard/dashboard_modules/google_analytics.py:168
-#: dashboard/dashboard_modules/yandex_metrika.py:120
+#: dashboard/dashboard_modules/yandex_metrika.py:123
 msgid "Last year"
 msgstr "Последний год"
 
 #: dashboard/dashboard_modules/google_analytics.py:178
-#: dashboard/dashboard_modules/yandex_metrika.py:130
+#: dashboard/dashboard_modules/yandex_metrika.py:133
 msgid "none"
 msgstr "не указано"
 
 #: dashboard/dashboard_modules/google_analytics.py:181
-#: dashboard/dashboard_modules/yandex_metrika.py:133
+#: dashboard/dashboard_modules/yandex_metrika.py:136
 msgid "grant access first"
 msgstr "сначала предоставьте доступ"
 
 #: dashboard/dashboard_modules/google_analytics.py:181
-#: dashboard/dashboard_modules/yandex_metrika.py:133
+#: dashboard/dashboard_modules/yandex_metrika.py:136
 msgid "counters loading failed"
 msgstr "не удалось загрузить счетчики"
 
 #: dashboard/dashboard_modules/google_analytics.py:186
-#: dashboard/dashboard_modules/yandex_metrika.py:138
+#: dashboard/dashboard_modules/yandex_metrika.py:141
 msgid "Show"
 msgstr "Показывать"
 
@@ -152,7 +152,7 @@ msgid "Sessions"
 msgstr "Сессии"
 
 #: dashboard/dashboard_modules/google_analytics.py:189
-#: dashboard/dashboard_modules/yandex_metrika.py:141
+#: dashboard/dashboard_modules/yandex_metrika.py:144
 #: dashboard/templates/jet.dashboard/modules/google_analytics_period_visitors.html:17
 #: dashboard/templates/jet.dashboard/modules/yandex_metrika_period_visitors.html:17
 msgid "Views"
@@ -160,29 +160,29 @@ msgstr "Просмотры"
 
 #: dashboard/dashboard_modules/google_analytics.py:191
 #: dashboard/dashboard_modules/google_analytics.py:199
-#: dashboard/dashboard_modules/yandex_metrika.py:143
-#: dashboard/dashboard_modules/yandex_metrika.py:151
+#: dashboard/dashboard_modules/yandex_metrika.py:146
+#: dashboard/dashboard_modules/yandex_metrika.py:154
 msgid "Group"
 msgstr "Группировать"
 
 #: dashboard/dashboard_modules/google_analytics.py:192
 #: dashboard/dashboard_modules/google_analytics.py:200
-#: dashboard/dashboard_modules/yandex_metrika.py:144
-#: dashboard/dashboard_modules/yandex_metrika.py:152
+#: dashboard/dashboard_modules/yandex_metrika.py:147
+#: dashboard/dashboard_modules/yandex_metrika.py:155
 msgid "By day"
 msgstr "По дням"
 
 #: dashboard/dashboard_modules/google_analytics.py:193
 #: dashboard/dashboard_modules/google_analytics.py:201
-#: dashboard/dashboard_modules/yandex_metrika.py:145
-#: dashboard/dashboard_modules/yandex_metrika.py:153
+#: dashboard/dashboard_modules/yandex_metrika.py:148
+#: dashboard/dashboard_modules/yandex_metrika.py:156
 msgid "By week"
 msgstr "По неделям"
 
 #: dashboard/dashboard_modules/google_analytics.py:194
 #: dashboard/dashboard_modules/google_analytics.py:202
-#: dashboard/dashboard_modules/yandex_metrika.py:146
-#: dashboard/dashboard_modules/yandex_metrika.py:154
+#: dashboard/dashboard_modules/yandex_metrika.py:149
+#: dashboard/dashboard_modules/yandex_metrika.py:157
 msgid "By month"
 msgstr "По месяцам"
 
@@ -205,13 +205,13 @@ msgstr ""
 
 #: dashboard/dashboard_modules/google_analytics.py:297
 #: dashboard/dashboard_modules/google_analytics_views.py:42
-#: dashboard/dashboard_modules/yandex_metrika.py:231
+#: dashboard/dashboard_modules/yandex_metrika.py:234
 #: dashboard/dashboard_modules/yandex_metrika_views.py:37
 msgid "API request failed."
 msgstr "Ошибка запроса к API."
 
 #: dashboard/dashboard_modules/google_analytics.py:299
-#: dashboard/dashboard_modules/yandex_metrika.py:233
+#: dashboard/dashboard_modules/yandex_metrika.py:236
 #, python-format
 msgid " Try to <a href=\"%s\">revoke and grant access</a> again"
 msgstr " Попробуйте <a href=\"%s\">убрать и предоставить доступ</a> заново"
@@ -229,16 +229,16 @@ msgid "sessions"
 msgstr "сессии"
 
 #: dashboard/dashboard_modules/google_analytics.py:318
-#: dashboard/dashboard_modules/yandex_metrika.py:254
+#: dashboard/dashboard_modules/yandex_metrika.py:257
 msgid "views"
 msgstr "просмотры"
 
 #: dashboard/dashboard_modules/google_analytics.py:320
 #: dashboard/dashboard_modules/google_analytics.py:365
 #: dashboard/dashboard_modules/google_analytics.py:404
-#: dashboard/dashboard_modules/yandex_metrika.py:256
-#: dashboard/dashboard_modules/yandex_metrika.py:295
-#: dashboard/dashboard_modules/yandex_metrika.py:328
+#: dashboard/dashboard_modules/yandex_metrika.py:259
+#: dashboard/dashboard_modules/yandex_metrika.py:298
+#: dashboard/dashboard_modules/yandex_metrika.py:331
 msgid "Bad server response"
 msgstr "Некорректный ответ сервера"
 
@@ -262,17 +262,17 @@ msgstr "Модуль не найден"
 msgid "Bad arguments"
 msgstr "Некорректные аргументы"
 
-#: dashboard/dashboard_modules/yandex_metrika.py:139
+#: dashboard/dashboard_modules/yandex_metrika.py:142
 #: dashboard/templates/jet.dashboard/modules/yandex_metrika_period_visitors.html:15
 msgid "Visitors"
 msgstr "Посетители"
 
-#: dashboard/dashboard_modules/yandex_metrika.py:140
+#: dashboard/dashboard_modules/yandex_metrika.py:143
 #: dashboard/templates/jet.dashboard/modules/yandex_metrika_period_visitors.html:16
 msgid "Visits"
 msgstr "Визиты"
 
-#: dashboard/dashboard_modules/yandex_metrika.py:214
+#: dashboard/dashboard_modules/yandex_metrika.py:217
 #, python-format
 msgid ""
 "Please <a href=\"%s\">attach Yandex account and choose Yandex Metrika "
@@ -281,35 +281,35 @@ msgstr ""
 "Пожалуйста <a href=\"%s\">прикрепите аккаунт Яндекс и выберите счетчик "
 "Яндекс Метрики</a> для виджета"
 
-#: dashboard/dashboard_modules/yandex_metrika.py:217
+#: dashboard/dashboard_modules/yandex_metrika.py:220
 #, python-format
 msgid ""
 "Please <a href=\"%s\">select Yandex Metrika counter</a> to start using widget"
 msgstr ""
 "Пожалуйста <a href=\"%s\">выберите счетчик Яндекс Метрики</a> для виджета"
 
-#: dashboard/dashboard_modules/yandex_metrika.py:240
+#: dashboard/dashboard_modules/yandex_metrika.py:243
 msgid "Yandex Metrika visitors totals"
 msgstr "Данные о посещениях Яндекс Метрики"
 
-#: dashboard/dashboard_modules/yandex_metrika.py:252
+#: dashboard/dashboard_modules/yandex_metrika.py:255
 msgid "visitors"
 msgstr "посетители"
 
-#: dashboard/dashboard_modules/yandex_metrika.py:253
+#: dashboard/dashboard_modules/yandex_metrika.py:256
 msgid "visits"
 msgstr "визиты"
 
-#: dashboard/dashboard_modules/yandex_metrika.py:260
+#: dashboard/dashboard_modules/yandex_metrika.py:263
 msgid "Yandex Metrika visitors chart"
 msgstr "График посещений Яндекс Метрики"
 
-#: dashboard/dashboard_modules/yandex_metrika.py:299
+#: dashboard/dashboard_modules/yandex_metrika.py:302
 msgid "Yandex Metrika period visitors"
 msgstr "Посещения Яндекс Метрики за период"
 
 #: dashboard/models.py:11 dashboard/modules.py:116
-#: templates/admin/base.html:189
+#: templates/admin/base.html:192
 msgid "Title"
 msgstr "Название"
 
@@ -353,7 +353,7 @@ msgstr ""
 msgid "user dashboard modules"
 msgstr ""
 
-#: dashboard/modules.py:115 models.py:12 templates/admin/base.html:191
+#: dashboard/modules.py:115 models.py:12 templates/admin/base.html:194
 msgid "URL"
 msgstr "URL"
 
@@ -407,7 +407,7 @@ msgstr "Необходимо указать корректный URL поток
 
 #: dashboard/templates/admin/app_index.html:32
 #: dashboard/templates/jet.dashboard/update_module.html:14
-#: templates/admin/base.html:92 templates/admin/base.html.py:141
+#: templates/admin/base.html:95 templates/admin/base.html.py:144
 #: templates/admin/change_form.html:17 templates/admin/change_list.html:33
 #: templates/admin/delete_confirmation.html:8
 #: templates/admin/delete_selected_confirmation.html:8
@@ -445,6 +445,15 @@ msgstr "изначальные"
 msgid "Add"
 msgstr ""
 
+#: dashboard/templates/jet.dashboard/dashboard_tools.html:21
+#: dashboard/templates/jet.dashboard/dashboard_tools.html:27
+msgid "Reset widgets"
+msgstr "Сбросить виджеты"
+
+#: dashboard/templates/jet.dashboard/dashboard_tools.html:28
+msgid "Are you sure want to reset widgets?"
+msgstr "Вы точно хотите сбросить виджеты?"
+
 #: dashboard/templates/jet.dashboard/module.html:19
 #: dashboard/templates/jet.dashboard/modules/app_list.html:24
 #: dashboard/templates/jet.dashboard/modules/model_list.html:14
@@ -508,7 +517,7 @@ msgid "Please correct the errors below."
 msgstr ""
 
 #: dashboard/templates/jet.dashboard/update_module.html:126
-#: templates/admin/base.html:211 templates/admin/base.html.py:218
+#: templates/admin/base.html:214 templates/admin/base.html.py:221
 #: templates/admin/edit_inline/stacked.html:21
 #: templates/admin/edit_inline/stacked.html:75
 #: templates/admin/edit_inline/tabular.html:100
@@ -551,7 +560,7 @@ msgstr ""
 msgid "bookmark"
 msgstr ""
 
-#: models.py:19 templates/admin/base.html:204
+#: models.py:19 templates/admin/base.html:207
 msgid "bookmarks"
 msgstr "закладки"
 
@@ -584,27 +593,27 @@ msgstr ""
 msgid "Clear selection"
 msgstr ""
 
-#: templates/admin/base.html:146
+#: templates/admin/base.html:149
 msgid "View site"
 msgstr ""
 
-#: templates/admin/base.html:186 templates/admin/base.html.py:203
+#: templates/admin/base.html:189 templates/admin/base.html.py:206
 msgid "Add bookmark"
 msgstr "Добавить закладку"
 
-#: templates/admin/base.html:199
+#: templates/admin/base.html:202
 msgid "Delete bookmark"
 msgstr "Удалить закладку"
 
-#: templates/admin/base.html:200
+#: templates/admin/base.html:203
 msgid "Are you sure want to delete this bookmark?"
 msgstr "Вы точно хотите удалить эту закладку?"
 
-#: templates/admin/base.html:226
+#: templates/admin/base.html:229
 msgid "Documentation"
 msgstr ""
 
-#: templates/admin/base.html:249
+#: templates/admin/base.html:252
 msgid "Application page"
 msgstr "Страница приложения"
 

二进制
jet/locale/ru/LC_MESSAGES/djangojs.mo


+ 16 - 9
jet/locale/ru/LC_MESSAGES/djangojs.po

@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-08-07 13:32+0000\n"
+"POT-Creation-Date: 2015-09-11 12:44+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -15,36 +15,43 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: static/jet/js/main.js:266
+#: static/jet/js/main.js:266 static/jet/js/main.min.js:1
 msgid "Add"
 msgstr "Добавить"
 
 #: static/jet/js/main.js:271 static/jet/js/main.js:315
-#: static/jet/js/main.js:721
+#: static/jet/js/main.js:766 static/jet/js/main.js:862
+#: static/jet/js/main.min.js:1 static/jet/js/main.min.js:2
+#: static/jet/js/main.min.js:3
 msgid "Cancel"
 msgstr "Отмена"
 
-#: static/jet/js/main.js:310 static/jet/js/main.js:716
+#: static/jet/js/main.js:310 static/jet/js/main.js:761
+#: static/jet/js/main.min.js:1 static/jet/js/main.min.js:2
 msgid "Delete"
 msgstr "Удалить"
 
-#: static/jet/js/main.js:336
+#: static/jet/js/main.js:336 static/jet/js/main.min.js:1
 msgid "Hide applications"
 msgstr "Скрыть приложения"
 
-#: static/jet/js/main.js:338
+#: static/jet/js/main.js:338 static/jet/js/main.min.js:1
 msgid "Show hidden"
 msgstr "Показать скрытые"
 
-#: static/jet/js/main.js:792
+#: static/jet/js/main.js:857 static/jet/js/main.min.js:3
+msgid "Yes"
+msgstr "Да"
+
+#: static/jet/js/main.js:884 static/jet/js/main.min.js:3
 msgid "Warning: you have unsaved changes"
 msgstr "Внимание: у вас есть несохраненные изменения"
 
-#: static/jet/js/select2.jet.js:108
+#: static/jet/js/select2.jet.js:108 static/jet/js/select2.jet.min.js:1
 msgid "select all"
 msgstr "выбрать все"
 
-#: static/jet/js/select2.jet.js:111
+#: static/jet/js/select2.jet.js:111 static/jet/js/select2.jet.min.js:1
 msgid "deselect all"
 msgstr "убрать все"
 

+ 2 - 0
jet/static/jet/css/_changelist.scss

@@ -11,6 +11,8 @@
 
     &-submit-block {
       white-space: nowrap;
+      line-height: 32px;
+      display: inline-block;
     }
   }
 

+ 21 - 1
jet/static/jet/css/_content.scss

@@ -108,4 +108,24 @@ ul.object-tools {
 }
 @-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
 @-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
-@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
+@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
+
+img[src$="admin/img/icon-yes.gif"], img[src$="admin/img/icon-no.gif"], img[src$="admin/img/icon-unknown.gif"] {
+  @include font-icon;
+  content: "";
+  font-weight: bold;
+}
+
+img[src$="admin/img/icon-yes.gif"]:before {
+  content: $icon-tick;
+  color: $success-text-color;
+}
+
+img[src$="admin/img/icon-no.gif"]:before {
+  content: $icon-cross;
+  color: $warning-text-color;
+}
+
+img[src$="admin/img/icon-unknown.gif"]:before {
+  content: $icon-question;
+}

+ 6 - 0
jet/static/jet/css/_forms.scss

@@ -62,6 +62,12 @@
     color: $background-button-text-color;
   }
 
+  &.button-transparent {
+    background-color: transparent;
+    color: $text-color;
+    padding: 0 10px;
+  }
+
   &:hover {
     background-color: $button-hover-background-color;
     color: $button-hover-text-color;

+ 26 - 2
jet/static/jet/css/_sidebar.scss

@@ -8,8 +8,9 @@
     margin-bottom: 32px !important;
 
     &-wrapper {
-      overflow-y: auto;
+      overflow: hidden;
       height: 100%;
+      position: relative;
     }
 
     &-item {
@@ -95,7 +96,7 @@
       &-list {
         @extend .clear-list;
 
-        &:not(:empty) {
+        .sidebar-menu-item-title + &:not(:empty) {
           margin-top: 10px !important;
         }
 
@@ -104,6 +105,17 @@
             display: none;
           }
 
+          &-icon {
+            font-size: 18px;
+            vertical-align: middle;
+            margin-right: 6px;
+            color: $sidebar-icon-color;
+          }
+
+          &.compact &-icon {
+            font-size: 16px;
+          }
+
           &-link {
             &, &:visited, &:hover {
               display: block;
@@ -172,6 +184,18 @@
             margin-left: 4px;
           }
         }
+
+        &.compact &-item-link {
+          &, &:visited, &:hover {
+            font-size: 11px;
+            padding: 6px 12px 6px 24px;
+            text-transform: uppercase;
+          }
+
+          &.padding-icon {
+            padding-left: 49px;
+          }
+        }
       }
     }
   }

+ 0 - 20
jet/static/jet/css/_table.scss

@@ -127,26 +127,6 @@
         &.action-checkbox {
           text-align: center;
         }
-
-        img[src$="admin/img/icon-yes.gif"], img[src$="admin/img/icon-no.gif"], img[src$="admin/img/icon-unknown.gif"] {
-          @include font-icon;
-          content: "";
-          font-weight: bold;
-        }
-
-        img[src$="admin/img/icon-yes.gif"]:before {
-          content: $icon-tick;
-          color: $success-text-color;
-        }
-
-        img[src$="admin/img/icon-no.gif"]:before {
-          content: $icon-cross;
-          color: $warning-text-color;
-        }
-
-        img[src$="admin/img/icon-unknown.gif"]:before {
-          content: $icon-question;
-        }
       }
     }
 

+ 1 - 0
jet/static/jet/css/icons/_variables.scss

@@ -1,3 +1,4 @@
+$icon-reset: "\e61e";
 $icon-search: "\e61d";
 $icon-user: "\e61c";
 $icon-jet: "\e61b";

二进制
jet/static/jet/css/icons/fonts/jet-icons.eot


+ 1 - 0
jet/static/jet/css/icons/fonts/jet-icons.svg

@@ -37,4 +37,5 @@
 <glyph unicode="&#xe61b;" glyph-name="jet" d="M136.192 156.16c0 0 54.886 51.2 74.547 28.058s-29.082-65.946-40.141-77.21c-11.264-11.264-79.053-23.962-91.136-73.114s-4.915 19.456 52.838 20.685c57.958 1.024 51.61-1.638 95.437 10.24s59.187 34.611 59.187 34.611 5.325-40.755-54.477-72.294c-59.802-31.539 37.069-3.482 76.186 17.818s62.464 70.246 62.464 70.246 3.072-26.214-36.454-91.75c0 0 159.744 91.341 101.786 235.315 0 0 1.843-72.499-48.538-131.277 0 0 9.216 56.934-6.758 63.693-11.469 4.915-36.659-88.064-77.21-92.774 0 0 29.082 41.574 18.432 56.525-15.155 21.299-87.45-38.707-87.45-38.707s3.686 53.043 79.462 98.714c0 0-29.491 7.782-61.645 1.024 0 0 56.115 46.899 123.699 41.37 0 0-36.864 24.166-71.475 18.842 0 0 14.336 28.877 87.245 26.419 0 0-107.52 55.296-211.149-40.55 0 0 58.778 28.672 93.389-4.506-0.205-0.205-119.194-9.011-138.24-101.376zM363.315 371.814l121.856-116.736c403.456 205.824 470.016 605.184 470.016 605.184s-303.923-45.67-591.872-488.448zM437.043 360.55l-26.624 21.504c283.648 371.712 460.8 409.6 460.8 409.6s-280.576-215.45-434.176-431.104zM508.723 107.827l-9.626 130.867c0 0 82.534 41.37 165.069 113.869zM214.835 397.619l131.072-14.336c0 0 27.853 48.333 119.808 159.744z" />
 <glyph unicode="&#xe61c;" glyph-name="user" d="M851.481 250.954c-39.072 50.987-86.335 84.097-154.057 102.883l-63.453-222.157c0-20.464-16.755-37.216-37.216-37.216-20.455 0-37.21 16.753-37.21 37.216v176.765c0 25.674-20.845 46.519-46.519 46.519s-46.516-20.847-46.516-46.519v-176.765c0-20.464-16.755-37.216-37.212-37.216-20.464 0-37.218 16.753-37.218 37.216l-63.453 222.157c-67.723-18.969-114.985-51.895-154.053-102.883-15.446-20.095-23.839-60.471-24.388-82.063 0.185-5.581 0-12.095 0-18.601v-74.435c0-41.12 33.309-74.425 74.43-74.425h576.815c41.12 0 74.435 33.305 74.435 74.425v74.435c0 6.505-0.182 13.019 0 18.601-0.563 21.591-8.946 61.97-24.383 82.063zM317.649 697.706c0-108.665 67.744-268.315 195.375-268.315 125.413 0 195.371 159.65 195.371 268.315 0 108.661-87.454 196.862-195.371 196.862s-195.375-88.201-195.375-196.862z" />
 <glyph unicode="&#xe61d;" glyph-name="search" d="M120.942 128.031l203.291 203.291c-38.651 53.090-61.716 118.249-61.716 188.955 0 177.713 144.047 321.759 321.759 321.759s321.759-144.047 321.759-321.759-144.047-321.759-321.759-321.759c-70.706 0-135.862 23.068-188.955 61.716l-203.291-203.291-71.089 71.089zM584.274 299.065c121.965 0 221.209 99.243 221.209 221.209s-99.243 221.209-221.209 221.209-221.209-99.243-221.209-221.209 99.243-221.209 221.209-221.209z" />
+<glyph unicode="&#xe61e;" glyph-name="reset" horiz-adv-x="1013" d="M1011.457 476.745c-56.408-0.485-112.778-0.784-169.149-1.269 9.482-97.062-22.511-197.371-96.838-271.586-131.966-131.929-345.801-131.929-477.692 0-131.929 131.817-131.929 345.689 0 477.618 112.554 112.591 284.652 128.607 414.714 49.016-44.088-43.566-95.942-95.158-95.942-95.158-37.331-39.646 0.635-65.927 25.759-66.077h329.562c12.618 0 22.772 10.191 22.809 22.809v326.874c1.531 30.798-32.292 59.432-65.554 26.132 0 0-55.81-55.213-94.56-93.664-198.080 144.771-477.244 128.345-656.174-50.547-197.856-197.856-197.856-518.645 0-716.464 197.819-197.782 518.608-197.782 716.427 0 107.664 107.589 156.195 251.614 146.638 392.316z" />
 </font></defs></svg>

二进制
jet/static/jet/css/icons/fonts/jet-icons.ttf


二进制
jet/static/jet/css/icons/fonts/jet-icons.woff


+ 8 - 5
jet/static/jet/css/icons/style.css

@@ -1,10 +1,10 @@
 @font-face {
 	font-family: 'jet-icons';
-	src:url('fonts/jet-icons.eot?-7wlpt4');
-	src:url('fonts/jet-icons.eot?#iefix-7wlpt4') format('embedded-opentype'),
-		url('fonts/jet-icons.ttf?-7wlpt4') format('truetype'),
-		url('fonts/jet-icons.woff?-7wlpt4') format('woff'),
-		url('fonts/jet-icons.svg?-7wlpt4#jet-icons') format('svg');
+	src:url('fonts/jet-icons.eot?-lem1jo');
+	src:url('fonts/jet-icons.eot?#iefix-lem1jo') format('embedded-opentype'),
+		url('fonts/jet-icons.ttf?-lem1jo') format('truetype'),
+		url('fonts/jet-icons.woff?-lem1jo') format('woff'),
+		url('fonts/jet-icons.svg?-lem1jo#jet-icons') format('svg');
 	font-weight: normal;
 	font-style: normal;
 }
@@ -23,6 +23,9 @@
 	-moz-osx-font-smoothing: grayscale;
 }
 
+.icon-reset:before {
+	content: "\e61e";
+}
 .icon-search:before {
 	content: "\e61d";
 }

+ 50 - 26
jet/static/jet/css/themes/default/base.css

@@ -729,28 +729,6 @@ a:hover {
       font-size: 13px; }
       .table tbody tr th.action-checkbox, #changelist table tbody tr th.action-checkbox, table#change-history tbody tr th.action-checkbox, .table tbody tr td.action-checkbox, #changelist table tbody tr td.action-checkbox, table#change-history tbody tr td.action-checkbox {
         text-align: center; }
-      .table tbody tr th img[src$="admin/img/icon-yes.gif"], #changelist table tbody tr th img[src$="admin/img/icon-yes.gif"], table#change-history tbody tr th img[src$="admin/img/icon-yes.gif"], .table tbody tr th img[src$="admin/img/icon-no.gif"], #changelist table tbody tr th img[src$="admin/img/icon-no.gif"], table#change-history tbody tr th img[src$="admin/img/icon-no.gif"], .table tbody tr th img[src$="admin/img/icon-unknown.gif"], #changelist table tbody tr th img[src$="admin/img/icon-unknown.gif"], table#change-history tbody tr th img[src$="admin/img/icon-unknown.gif"], .table tbody tr td img[src$="admin/img/icon-yes.gif"], #changelist table tbody tr td img[src$="admin/img/icon-yes.gif"], table#change-history tbody tr td img[src$="admin/img/icon-yes.gif"], .table tbody tr td img[src$="admin/img/icon-no.gif"], #changelist table tbody tr td img[src$="admin/img/icon-no.gif"], table#change-history tbody tr td img[src$="admin/img/icon-no.gif"], .table tbody tr td img[src$="admin/img/icon-unknown.gif"], #changelist table tbody tr td img[src$="admin/img/icon-unknown.gif"], table#change-history tbody tr td img[src$="admin/img/icon-unknown.gif"] {
-        font-family: 'jet-icons';
-        speak: none;
-        font-style: normal;
-        font-weight: normal;
-        font-variant: normal;
-        text-transform: none;
-        line-height: 1;
-        /* Better Font Rendering =========== */
-        -webkit-font-smoothing: antialiased;
-        -moz-osx-font-smoothing: grayscale;
-        display: inline-block;
-        content: "";
-        font-weight: bold; }
-      .table tbody tr th img[src$="admin/img/icon-yes.gif"]:before, #changelist table tbody tr th img[src$="admin/img/icon-yes.gif"]:before, table#change-history tbody tr th img[src$="admin/img/icon-yes.gif"]:before, .table tbody tr td img[src$="admin/img/icon-yes.gif"]:before, #changelist table tbody tr td img[src$="admin/img/icon-yes.gif"]:before, table#change-history tbody tr td img[src$="admin/img/icon-yes.gif"]:before {
-        content: "";
-        color: #8ecb8e; }
-      .table tbody tr th img[src$="admin/img/icon-no.gif"]:before, #changelist table tbody tr th img[src$="admin/img/icon-no.gif"]:before, table#change-history tbody tr th img[src$="admin/img/icon-no.gif"]:before, .table tbody tr td img[src$="admin/img/icon-no.gif"]:before, #changelist table tbody tr td img[src$="admin/img/icon-no.gif"]:before, table#change-history tbody tr td img[src$="admin/img/icon-no.gif"]:before {
-        content: "";
-        color: #dba4a4; }
-      .table tbody tr th img[src$="admin/img/icon-unknown.gif"]:before, #changelist table tbody tr th img[src$="admin/img/icon-unknown.gif"]:before, table#change-history tbody tr th img[src$="admin/img/icon-unknown.gif"]:before, .table tbody tr td img[src$="admin/img/icon-unknown.gif"]:before, #changelist table tbody tr td img[src$="admin/img/icon-unknown.gif"]:before, table#change-history tbody tr td img[src$="admin/img/icon-unknown.gif"]:before {
-        content: ""; }
   .table tbody tr.selected, #changelist table tbody tr.selected, table#change-history tbody tr.selected {
     border-color: #e5e2a5; }
     .table tbody tr.selected:last-child th:first-child, #changelist table tbody tr.selected:last-child th:first-child, table#change-history tbody tr.selected:last-child th:first-child, .table tbody tr.selected:last-child td:first-child, #changelist table tbody tr.selected:last-child td:first-child, table#change-history tbody tr.selected:last-child td:first-child {
@@ -1394,8 +1372,9 @@ a:hover {
   .sidebar-menu {
     margin-bottom: 32px !important; }
     .sidebar-menu-wrapper {
-      overflow-y: auto;
-      height: 100%; }
+      overflow: hidden;
+      height: 100%;
+      position: relative; }
     .sidebar-menu-item {
       padding: 20px 24px;
       border-bottom: 1px solid #2b3647; }
@@ -1458,10 +1437,17 @@ a:hover {
       .sidebar-menu-item-action:hover {
         color: #639af5;
         background-color: #2b3647; }
-      .sidebar-menu-item-list:not(:empty) {
+      .sidebar-menu-item-title + .sidebar-menu-item-list:not(:empty) {
         margin-top: 10px !important; }
       .sidebar-menu-item-list-item.empty {
         display: none; }
+      .sidebar-menu-item-list-item-icon {
+        font-size: 18px;
+        vertical-align: middle;
+        margin-right: 6px;
+        color: #6f7e95; }
+      .sidebar-menu-item-list-item.compact .sidebar-menu-item-list-item-icon {
+        font-size: 16px; }
       .sidebar-menu-item-list-item-link, .sidebar-menu-item-list-item-link:visited, .sidebar-menu-item-list-item-link:hover {
         display: block;
         color: #c0cad8;
@@ -1513,6 +1499,12 @@ a:hover {
         font-size: 16px;
         font-weight: bold !important;
         margin-left: 4px; }
+      .sidebar-menu-item-list.compact .sidebar-menu-item-list-item-link, .sidebar-menu-item-list.compact .sidebar-menu-item-list-item-link:visited, .sidebar-menu-item-list.compact .sidebar-menu-item-list-item-link:hover {
+        font-size: 11px;
+        padding: 6px 12px 6px 24px;
+        text-transform: uppercase; }
+      .sidebar-menu-item-list.compact .sidebar-menu-item-list-item-link.padding-icon {
+        padding-left: 49px; }
   .sidebar-popup {
     position: absolute;
     top: 0;
@@ -2294,6 +2286,10 @@ a:hover {
 .button.button-background, input.button-background[type="submit"], input.button-background[type="button"] {
   background-color: #fff;
   color: #6f7e95; }
+.button.button-transparent, input.button-transparent[type="submit"], input.button-transparent[type="button"] {
+  background-color: transparent;
+  color: #6f7e95;
+  padding: 0 10px; }
 .button:hover, input[type="submit"]:hover, input[type="button"]:hover {
   background-color: #639af5;
   color: #fff;
@@ -2985,7 +2981,9 @@ input[type=checkbox] {
   #changelist .changelist-filter * {
     vertical-align: top; }
   #changelist .changelist-filter-submit-block {
-    white-space: nowrap; }
+    white-space: nowrap;
+    line-height: 32px;
+    display: inline-block; }
 #changelist .results {
   overflow-x: auto; }
 #changelist table {
@@ -4684,6 +4682,32 @@ ul.object-tools {
   100% {
     -webkit-transform: rotate(360deg);
     transform: rotate(360deg); } }
+img[src$="admin/img/icon-yes.gif"], img[src$="admin/img/icon-no.gif"], img[src$="admin/img/icon-unknown.gif"] {
+  font-family: 'jet-icons';
+  speak: none;
+  font-style: normal;
+  font-weight: normal;
+  font-variant: normal;
+  text-transform: none;
+  line-height: 1;
+  /* Better Font Rendering =========== */
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  display: inline-block;
+  content: "";
+  font-weight: bold; }
+
+img[src$="admin/img/icon-yes.gif"]:before {
+  content: "";
+  color: #8ecb8e; }
+
+img[src$="admin/img/icon-no.gif"]:before {
+  content: "";
+  color: #dba4a4; }
+
+img[src$="admin/img/icon-unknown.gif"]:before {
+  content: ""; }
+
 /*
  * General
  */

文件差异内容过多而无法显示
+ 0 - 0
jet/static/jet/css/themes/default/base.css.map


文件差异内容过多而无法显示
+ 0 - 0
jet/static/jet/css/themes/default/jquery-ui.theme.css.map


文件差异内容过多而无法显示
+ 0 - 0
jet/static/jet/css/themes/default/select2.theme.css.map


+ 50 - 26
jet/static/jet/css/themes/green/base.css

@@ -760,28 +760,6 @@ a:hover {
       font-size: 13px; }
       .table tbody tr th.action-checkbox, #changelist table tbody tr th.action-checkbox, table#change-history tbody tr th.action-checkbox, .table tbody tr td.action-checkbox, #changelist table tbody tr td.action-checkbox, table#change-history tbody tr td.action-checkbox {
         text-align: center; }
-      .table tbody tr th img[src$="admin/img/icon-yes.gif"], #changelist table tbody tr th img[src$="admin/img/icon-yes.gif"], table#change-history tbody tr th img[src$="admin/img/icon-yes.gif"], .table tbody tr th img[src$="admin/img/icon-no.gif"], #changelist table tbody tr th img[src$="admin/img/icon-no.gif"], table#change-history tbody tr th img[src$="admin/img/icon-no.gif"], .table tbody tr th img[src$="admin/img/icon-unknown.gif"], #changelist table tbody tr th img[src$="admin/img/icon-unknown.gif"], table#change-history tbody tr th img[src$="admin/img/icon-unknown.gif"], .table tbody tr td img[src$="admin/img/icon-yes.gif"], #changelist table tbody tr td img[src$="admin/img/icon-yes.gif"], table#change-history tbody tr td img[src$="admin/img/icon-yes.gif"], .table tbody tr td img[src$="admin/img/icon-no.gif"], #changelist table tbody tr td img[src$="admin/img/icon-no.gif"], table#change-history tbody tr td img[src$="admin/img/icon-no.gif"], .table tbody tr td img[src$="admin/img/icon-unknown.gif"], #changelist table tbody tr td img[src$="admin/img/icon-unknown.gif"], table#change-history tbody tr td img[src$="admin/img/icon-unknown.gif"] {
-        font-family: 'jet-icons';
-        speak: none;
-        font-style: normal;
-        font-weight: normal;
-        font-variant: normal;
-        text-transform: none;
-        line-height: 1;
-        /* Better Font Rendering =========== */
-        -webkit-font-smoothing: antialiased;
-        -moz-osx-font-smoothing: grayscale;
-        display: inline-block;
-        content: "";
-        font-weight: bold; }
-      .table tbody tr th img[src$="admin/img/icon-yes.gif"]:before, #changelist table tbody tr th img[src$="admin/img/icon-yes.gif"]:before, table#change-history tbody tr th img[src$="admin/img/icon-yes.gif"]:before, .table tbody tr td img[src$="admin/img/icon-yes.gif"]:before, #changelist table tbody tr td img[src$="admin/img/icon-yes.gif"]:before, table#change-history tbody tr td img[src$="admin/img/icon-yes.gif"]:before {
-        content: "";
-        color: #bcd386; }
-      .table tbody tr th img[src$="admin/img/icon-no.gif"]:before, #changelist table tbody tr th img[src$="admin/img/icon-no.gif"]:before, table#change-history tbody tr th img[src$="admin/img/icon-no.gif"]:before, .table tbody tr td img[src$="admin/img/icon-no.gif"]:before, #changelist table tbody tr td img[src$="admin/img/icon-no.gif"]:before, table#change-history tbody tr td img[src$="admin/img/icon-no.gif"]:before {
-        content: "";
-        color: #dba4a4; }
-      .table tbody tr th img[src$="admin/img/icon-unknown.gif"]:before, #changelist table tbody tr th img[src$="admin/img/icon-unknown.gif"]:before, table#change-history tbody tr th img[src$="admin/img/icon-unknown.gif"]:before, .table tbody tr td img[src$="admin/img/icon-unknown.gif"]:before, #changelist table tbody tr td img[src$="admin/img/icon-unknown.gif"]:before, table#change-history tbody tr td img[src$="admin/img/icon-unknown.gif"]:before {
-        content: ""; }
   .table tbody tr.selected, #changelist table tbody tr.selected, table#change-history tbody tr.selected {
     border-color: #e5e2a5; }
     .table tbody tr.selected:last-child th:first-child, #changelist table tbody tr.selected:last-child th:first-child, table#change-history tbody tr.selected:last-child th:first-child, .table tbody tr.selected:last-child td:first-child, #changelist table tbody tr.selected:last-child td:first-child, table#change-history tbody tr.selected:last-child td:first-child {
@@ -1425,8 +1403,9 @@ a:hover {
   .sidebar-menu {
     margin-bottom: 32px !important; }
     .sidebar-menu-wrapper {
-      overflow-y: auto;
-      height: 100%; }
+      overflow: hidden;
+      height: 100%;
+      position: relative; }
     .sidebar-menu-item {
       padding: 20px 24px;
       border-bottom: 1px solid #254d49; }
@@ -1489,10 +1468,17 @@ a:hover {
       .sidebar-menu-item-action:hover {
         color: #7FB1DC;
         background-color: #254d49; }
-      .sidebar-menu-item-list:not(:empty) {
+      .sidebar-menu-item-title + .sidebar-menu-item-list:not(:empty) {
         margin-top: 10px !important; }
       .sidebar-menu-item-list-item.empty {
         display: none; }
+      .sidebar-menu-item-list-item-icon {
+        font-size: 18px;
+        vertical-align: middle;
+        margin-right: 6px;
+        color: #62a29c; }
+      .sidebar-menu-item-list-item.compact .sidebar-menu-item-list-item-icon {
+        font-size: 16px; }
       .sidebar-menu-item-list-item-link, .sidebar-menu-item-list-item-link:visited, .sidebar-menu-item-list-item-link:hover {
         display: block;
         color: #bbddd9;
@@ -1544,6 +1530,12 @@ a:hover {
         font-size: 16px;
         font-weight: bold !important;
         margin-left: 4px; }
+      .sidebar-menu-item-list.compact .sidebar-menu-item-list-item-link, .sidebar-menu-item-list.compact .sidebar-menu-item-list-item-link:visited, .sidebar-menu-item-list.compact .sidebar-menu-item-list-item-link:hover {
+        font-size: 11px;
+        padding: 6px 12px 6px 24px;
+        text-transform: uppercase; }
+      .sidebar-menu-item-list.compact .sidebar-menu-item-list-item-link.padding-icon {
+        padding-left: 49px; }
   .sidebar-popup {
     position: absolute;
     top: 0;
@@ -2325,6 +2317,10 @@ a:hover {
 .button.button-background, input.button-background[type="submit"], input.button-background[type="button"] {
   background-color: white;
   color: #62a29c; }
+.button.button-transparent, input.button-transparent[type="submit"], input.button-transparent[type="button"] {
+  background-color: transparent;
+  color: #62a29c;
+  padding: 0 10px; }
 .button:hover, input[type="submit"]:hover, input[type="button"]:hover {
   background-color: #7FB1DC;
   color: white;
@@ -3016,7 +3012,9 @@ input[type=checkbox] {
   #changelist .changelist-filter * {
     vertical-align: top; }
   #changelist .changelist-filter-submit-block {
-    white-space: nowrap; }
+    white-space: nowrap;
+    line-height: 32px;
+    display: inline-block; }
 #changelist .results {
   overflow-x: auto; }
 #changelist table {
@@ -4715,6 +4713,32 @@ ul.object-tools {
   100% {
     -webkit-transform: rotate(360deg);
     transform: rotate(360deg); } }
+img[src$="admin/img/icon-yes.gif"], img[src$="admin/img/icon-no.gif"], img[src$="admin/img/icon-unknown.gif"] {
+  font-family: 'jet-icons';
+  speak: none;
+  font-style: normal;
+  font-weight: normal;
+  font-variant: normal;
+  text-transform: none;
+  line-height: 1;
+  /* Better Font Rendering =========== */
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  display: inline-block;
+  content: "";
+  font-weight: bold; }
+
+img[src$="admin/img/icon-yes.gif"]:before {
+  content: "";
+  color: #bcd386; }
+
+img[src$="admin/img/icon-no.gif"]:before {
+  content: "";
+  color: #dba4a4; }
+
+img[src$="admin/img/icon-unknown.gif"]:before {
+  content: ""; }
+
 /*
  * General
  */

文件差异内容过多而无法显示
+ 0 - 0
jet/static/jet/css/themes/green/base.css.map


文件差异内容过多而无法显示
+ 0 - 0
jet/static/jet/css/themes/green/jquery-ui.theme.css.map


文件差异内容过多而无法显示
+ 0 - 0
jet/static/jet/css/themes/green/select2.theme.css.map


+ 43 - 0
jet/static/jet/js/main.js

@@ -833,6 +833,44 @@
                     }
                 });
             });
+
+            $('.reset-dashboard-link').on('click', function(e) {
+                var buttons = {};
+                var resetDashboard = function () {
+                    var $form = $('#reset-dashboard-form');
+
+                    $.ajax({
+                        url: $form.attr('action'),
+                        method: $form.attr('method'),
+                        dataType: 'json',
+                        data: $form.serialize(),
+                        success: function (result) {
+                            if (result.error) {
+                                return;
+                            }
+
+                            location.reload();
+                        }
+                    });
+                };
+
+                buttons[django.gettext('Yes')] = function() {
+                    resetDashboard();
+                    $(this).dialog('close');
+                };
+
+                buttons[django.gettext('Cancel')] = function() {
+                    $(this).dialog('close');
+                };
+
+                $('#reset-dashboard-dialog').dialog({
+                    resizable: false,
+                    modal: true,
+                    buttons: buttons
+                });
+
+                e.preventDefault();
+            });
         };
 
         var initUnsavedChangesWarning = function() {
@@ -864,6 +902,10 @@
             }
         };
 
+        var initScrollbars = function() {
+            $('.sidebar-menu-wrapper').perfectScrollbar();
+        };
+
         initjQueryCaseInsensitiveSelector();
         initjQuerySlideFadeToggle();
         initFilters();
@@ -878,5 +920,6 @@
         initTooltips();
         initDashboard();
         initUnsavedChangesWarning();
+        initScrollbars();
     });
 })(jet.jQuery);

文件差异内容过多而无法显示
+ 0 - 0
jet/static/jet/js/main.min.js


+ 108 - 0
jet/static/jet/vendor/perfect-scrollbar/css/perfect-scrollbar.css

@@ -0,0 +1,108 @@
+/* perfect-scrollbar v0.6.5 */
+.ps-container {
+  -ms-touch-action: none;
+  overflow: hidden !important; }
+  .ps-container.ps-active-x > .ps-scrollbar-x-rail, .ps-container.ps-active-y > .ps-scrollbar-y-rail {
+    display: block; }
+  .ps-container.ps-in-scrolling {
+    pointer-events: none; }
+    .ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail {
+      background-color: #eee;
+      opacity: 0.9; }
+      .ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {
+        background-color: #999; }
+    .ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {
+      background-color: #eee;
+      opacity: 0.9; }
+      .ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {
+        background-color: #999; }
+  .ps-container > .ps-scrollbar-x-rail {
+    display: none;
+    position: absolute;
+    /* please don't change 'position' */
+    -webkit-border-radius: 4px;
+    -moz-border-radius: 4px;
+    -ms-border-radius: 4px;
+    border-radius: 4px;
+    opacity: 0;
+    -webkit-transition: background-color .2s linear, opacity .2s linear;
+    -moz-transition: background-color .2s linear, opacity .2s linear;
+    -o-transition: background-color .2s linear, opacity .2s linear;
+    transition: background-color .2s linear, opacity .2s linear;
+    bottom: 3px;
+    /* there must be 'bottom' for ps-scrollbar-x-rail */
+    height: 8px;
+    margin: 0 3px; }
+    .ps-container > .ps-scrollbar-x-rail > .ps-scrollbar-x {
+      position: absolute;
+      /* please don't change 'position' */
+      background-color: #aaa;
+      -webkit-border-radius: 4px;
+      -moz-border-radius: 4px;
+      -ms-border-radius: 4px;
+      border-radius: 4px;
+      -webkit-transition: background-color .2s linear;
+      -moz-transition: background-color .2s linear;
+      -o-transition: background-color .2s linear;
+      transition: background-color .2s linear;
+      bottom: 0;
+      /* there must be 'bottom' for ps-scrollbar-x */
+      height: 8px; }
+  .ps-container > .ps-scrollbar-y-rail {
+    display: none;
+    position: absolute;
+    /* please don't change 'position' */
+    -webkit-border-radius: 4px;
+    -moz-border-radius: 4px;
+    -ms-border-radius: 4px;
+    border-radius: 4px;
+    opacity: 0;
+    -webkit-transition: background-color .2s linear, opacity .2s linear;
+    -moz-transition: background-color .2s linear, opacity .2s linear;
+    -o-transition: background-color .2s linear, opacity .2s linear;
+    transition: background-color .2s linear, opacity .2s linear;
+    right: 3px;
+    /* there must be 'right' for ps-scrollbar-y-rail */
+    width: 8px;
+    margin: 3px 0; }
+    .ps-container > .ps-scrollbar-y-rail > .ps-scrollbar-y {
+      position: absolute;
+      /* please don't change 'position' */
+      background-color: #aaa;
+      -webkit-border-radius: 4px;
+      -moz-border-radius: 4px;
+      -ms-border-radius: 4px;
+      border-radius: 4px;
+      -webkit-transition: background-color .2s linear;
+      -moz-transition: background-color .2s linear;
+      -o-transition: background-color .2s linear;
+      transition: background-color .2s linear;
+      right: 0;
+      /* there must be 'right' for ps-scrollbar-y */
+      width: 8px; }
+  .ps-container:hover.ps-in-scrolling {
+    pointer-events: none; }
+    .ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail {
+      background-color: #eee;
+      opacity: 0.9; }
+      .ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x {
+        background-color: #999; }
+    .ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail {
+      background-color: #eee;
+      opacity: 0.9; }
+      .ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y {
+        background-color: #999; }
+  .ps-container:hover > .ps-scrollbar-x-rail, .ps-container:hover:hover > .ps-scrollbar-y-rail {
+    opacity: 0.6; }
+  .ps-container:hover > .ps-scrollbar-x-rail:hover {
+    background-color: #eee;
+    opacity: 0.9; }
+    .ps-container:hover > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x {
+      background-color: #999; }
+  .ps-container:hover > .ps-scrollbar-y-rail:hover {
+    background-color: #eee;
+    opacity: 0.9; }
+    .ps-container:hover > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y {
+      background-color: #999; }
+
+/*# sourceMappingURL=perfect-scrollbar.css.map */

+ 7 - 0
jet/static/jet/vendor/perfect-scrollbar/css/perfect-scrollbar.css.map

@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": ";AACA,aAAc;EACZ,gBAAgB,EAAE,IAAI;EACtB,QAAQ,EAAE,iBAAiB;EAE3B,kGAA2E;IACzE,OAAO,EAAE,KAAK;EAGhB,6BAAkB;IAChB,cAAc,EAAE,IAAI;IAEpB,yDAA8B;MAC5B,gBAAgB,EAAE,IAAI;MACtB,OAAO,EAAE,GAAG;MAEZ,2EAAoB;QAClB,gBAAgB,EAAE,IAAI;IAI1B,yDAA8B;MAC5B,gBAAgB,EAAE,IAAI;MACtB,OAAO,EAAE,GAAG;MAEZ,2EAAoB;QAClB,gBAAgB,EAAE,IAAI;EAK5B,oCAAyB;IACvB,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,QAAQ;;IAElB,qBAAqB,EAAE,GAAG;IAC1B,kBAAkB,EAAE,GAAG;IACvB,iBAAiB,EAAE,GAAG;IACtB,aAAa,EAAE,GAAG;IAClB,OAAO,EAAE,CAAC;IACV,kBAAkB,EAAE,+CAA+C;IACnE,eAAe,EAAE,+CAA+C;IAChE,aAAa,EAAE,+CAA+C;IAC9D,UAAU,EAAE,+CAA+C;IAC3D,MAAM,EAAE,GAAG;;IAEX,MAAM,EAAE,GAAG;IACX,MAAM,EAAE,KAAK;IAEb,sDAAoB;MAClB,QAAQ,EAAE,QAAQ;;MAElB,gBAAgB,EAAE,IAAI;MACtB,qBAAqB,EAAE,GAAG;MAC1B,kBAAkB,EAAE,GAAG;MACvB,iBAAiB,EAAE,GAAG;MACtB,aAAa,EAAE,GAAG;MAClB,kBAAkB,EAAE,2BAA2B;MAC/C,eAAe,EAAE,2BAA2B;MAC5C,aAAa,EAAE,2BAA2B;MAC1C,UAAU,EAAE,2BAA2B;MACvC,MAAM,EAAE,CAAC;;MAET,MAAM,EAAE,GAAG;EAIf,oCAAyB;IACvB,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,QAAQ;;IAElB,qBAAqB,EAAE,GAAG;IAC1B,kBAAkB,EAAE,GAAG;IACvB,iBAAiB,EAAE,GAAG;IACtB,aAAa,EAAE,GAAG;IAClB,OAAO,EAAE,CAAC;IACV,kBAAkB,EAAE,+CAA+C;IACnE,eAAe,EAAE,+CAA+C;IAChE,aAAa,EAAE,+CAA+C;IAC9D,UAAU,EAAE,+CAA+C;IAC3D,KAAK,EAAE,GAAG;;IAEV,KAAK,EAAE,GAAG;IACV,MAAM,EAAE,KAAK;IAEb,sDAAoB;MAClB,QAAQ,EAAE,QAAQ;;MAElB,gBAAgB,EAAE,IAAI;MACtB,qBAAqB,EAAE,GAAG;MAC1B,kBAAkB,EAAE,GAAG;MACvB,iBAAiB,EAAE,GAAG;MACtB,aAAa,EAAE,GAAG;MAClB,kBAAkB,EAAE,2BAA2B;MAC/C,eAAe,EAAE,2BAA2B;MAC5C,aAAa,EAAE,2BAA2B;MAC1C,UAAU,EAAE,2BAA2B;MACvC,KAAK,EAAE,CAAC;;MAER,KAAK,EAAE,GAAG;EAId,mCAAwB;IACtB,cAAc,EAAE,IAAI;IAEpB,+DAA8B;MAC5B,gBAAgB,EAAE,IAAI;MACtB,OAAO,EAAE,GAAG;MAEZ,iFAAoB;QAClB,gBAAgB,EAAE,IAAI;IAI1B,+DAA8B;MAC5B,gBAAgB,EAAE,IAAI;MACtB,OAAO,EAAE,GAAG;MAEZ,iFAAoB;QAClB,gBAAgB,EAAE,IAAI;EAM1B,4FAAyD;IACvD,OAAO,EAAE,GAAG;EAGd,gDAA+B;IAC7B,gBAAgB,EAAE,IAAI;IACtB,OAAO,EAAE,GAAG;IAEZ,kEAAoB;MAClB,gBAAgB,EAAE,IAAI;EAI1B,gDAA+B;IAC7B,gBAAgB,EAAE,IAAI;IACtB,OAAO,EAAE,GAAG;IAEZ,kEAAoB;MAClB,gBAAgB,EAAE,IAAI",
+"sources": ["perfect-scrollbar.scss"],
+"names": [],
+"file": "perfect-scrollbar.css"
+}

+ 149 - 0
jet/static/jet/vendor/perfect-scrollbar/css/perfect-scrollbar.scss

@@ -0,0 +1,149 @@
+/* perfect-scrollbar v0.6.5 */
+.ps-container {
+  -ms-touch-action: none;
+  overflow: hidden !important;
+
+  &.ps-active-x > .ps-scrollbar-x-rail, &.ps-active-y > .ps-scrollbar-y-rail {
+    display: block;
+  }
+
+  &.ps-in-scrolling {
+    pointer-events: none;
+
+    &.ps-x > .ps-scrollbar-x-rail {
+      background-color: #eee;
+      opacity: 0.9;
+
+      & > .ps-scrollbar-x {
+        background-color: #999;
+      }
+    }
+
+    &.ps-y > .ps-scrollbar-y-rail {
+      background-color: #eee;
+      opacity: 0.9;
+
+      & > .ps-scrollbar-y {
+        background-color: #999;
+      }
+    }
+  }
+
+  & > .ps-scrollbar-x-rail {
+    display: none;
+    position: absolute;
+    /* please don't change 'position' */
+    -webkit-border-radius: 4px;
+    -moz-border-radius: 4px;
+    -ms-border-radius: 4px;
+    border-radius: 4px;
+    opacity: 0;
+    -webkit-transition: background-color .2s linear, opacity .2s linear;
+    -moz-transition: background-color .2s linear, opacity .2s linear;
+    -o-transition: background-color .2s linear, opacity .2s linear;
+    transition: background-color .2s linear, opacity .2s linear;
+    bottom: 3px;
+    /* there must be 'bottom' for ps-scrollbar-x-rail */
+    height: 8px;
+    margin: 0 3px;
+
+    & > .ps-scrollbar-x {
+      position: absolute;
+      /* please don't change 'position' */
+      background-color: #aaa;
+      -webkit-border-radius: 4px;
+      -moz-border-radius: 4px;
+      -ms-border-radius: 4px;
+      border-radius: 4px;
+      -webkit-transition: background-color .2s linear;
+      -moz-transition: background-color .2s linear;
+      -o-transition: background-color .2s linear;
+      transition: background-color .2s linear;
+      bottom: 0;
+      /* there must be 'bottom' for ps-scrollbar-x */
+      height: 8px;
+    }
+  }
+
+  & > .ps-scrollbar-y-rail {
+    display: none;
+    position: absolute;
+    /* please don't change 'position' */
+    -webkit-border-radius: 4px;
+    -moz-border-radius: 4px;
+    -ms-border-radius: 4px;
+    border-radius: 4px;
+    opacity: 0;
+    -webkit-transition: background-color .2s linear, opacity .2s linear;
+    -moz-transition: background-color .2s linear, opacity .2s linear;
+    -o-transition: background-color .2s linear, opacity .2s linear;
+    transition: background-color .2s linear, opacity .2s linear;
+    right: 3px;
+    /* there must be 'right' for ps-scrollbar-y-rail */
+    width: 8px;
+    margin: 3px 0;
+
+    & > .ps-scrollbar-y {
+      position: absolute;
+      /* please don't change 'position' */
+      background-color: #aaa;
+      -webkit-border-radius: 4px;
+      -moz-border-radius: 4px;
+      -ms-border-radius: 4px;
+      border-radius: 4px;
+      -webkit-transition: background-color .2s linear;
+      -moz-transition: background-color .2s linear;
+      -o-transition: background-color .2s linear;
+      transition: background-color .2s linear;
+      right: 0;
+      /* there must be 'right' for ps-scrollbar-y */
+      width: 8px;
+    }
+  }
+
+  &:hover.ps-in-scrolling {
+    pointer-events: none;
+
+    &.ps-x > .ps-scrollbar-x-rail {
+      background-color: #eee;
+      opacity: 0.9;
+
+      & > .ps-scrollbar-x {
+        background-color: #999;
+      }
+    }
+
+    &.ps-y > .ps-scrollbar-y-rail {
+      background-color: #eee;
+      opacity: 0.9;
+
+      & > .ps-scrollbar-y {
+        background-color: #999;
+      }
+    }
+  }
+
+  &:hover {
+    & > .ps-scrollbar-x-rail, &:hover > .ps-scrollbar-y-rail {
+      opacity: 0.6;
+    }
+
+    & > .ps-scrollbar-x-rail:hover {
+      background-color: #eee;
+      opacity: 0.9;
+
+      & > .ps-scrollbar-x {
+        background-color: #999;
+      }
+    }
+
+    & > .ps-scrollbar-y-rail:hover {
+      background-color: #eee;
+      opacity: 0.9;
+
+      & > .ps-scrollbar-y {
+        background-color: #999;
+      }
+    }
+  }
+}

+ 1492 - 0
jet/static/jet/vendor/perfect-scrollbar/js/perfect-scrollbar.jquery.js

@@ -0,0 +1,1492 @@
+/* perfect-scrollbar v0.6.5 */
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var ps = require('../main')
+  , psInstances = require('../plugin/instances');
+
+function mountJQuery(jQuery) {
+  jQuery.fn.perfectScrollbar = function (settingOrCommand) {
+    return this.each(function () {
+      if (typeof settingOrCommand === 'object' ||
+          typeof settingOrCommand === 'undefined') {
+        // If it's an object or none, initialize.
+        var settings = settingOrCommand;
+
+        if (!psInstances.get(this)) {
+          ps.initialize(this, settings);
+        }
+      } else {
+        // Unless, it may be a command.
+        var command = settingOrCommand;
+
+        if (command === 'update') {
+          ps.update(this);
+        } else if (command === 'destroy') {
+          ps.destroy(this);
+        }
+      }
+
+      return jQuery(this);
+    });
+  };
+}
+
+if (typeof define === 'function' && define.amd) {
+  // AMD. Register as an anonymous module.
+  define(['jquery'], mountJQuery);
+} else {
+  var jq = window.jQuery ? window.jQuery : window.$;
+  if (typeof jq !== 'undefined') {
+    mountJQuery(jq);
+  }
+}
+
+module.exports = mountJQuery;
+
+},{"../main":7,"../plugin/instances":18}],2:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+function oldAdd(element, className) {
+  var classes = element.className.split(' ');
+  if (classes.indexOf(className) < 0) {
+    classes.push(className);
+  }
+  element.className = classes.join(' ');
+}
+
+function oldRemove(element, className) {
+  var classes = element.className.split(' ');
+  var idx = classes.indexOf(className);
+  if (idx >= 0) {
+    classes.splice(idx, 1);
+  }
+  element.className = classes.join(' ');
+}
+
+exports.add = function (element, className) {
+  if (element.classList) {
+    element.classList.add(className);
+  } else {
+    oldAdd(element, className);
+  }
+};
+
+exports.remove = function (element, className) {
+  if (element.classList) {
+    element.classList.remove(className);
+  } else {
+    oldRemove(element, className);
+  }
+};
+
+exports.list = function (element) {
+  if (element.classList) {
+    return element.classList;
+  } else {
+    return element.className.split(' ');
+  }
+};
+
+},{}],3:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var DOM = {};
+
+DOM.e = function (tagName, className) {
+  var element = document.createElement(tagName);
+  element.className = className;
+  return element;
+};
+
+DOM.appendTo = function (child, parent) {
+  parent.appendChild(child);
+  return child;
+};
+
+function cssGet(element, styleName) {
+  return window.getComputedStyle(element)[styleName];
+}
+
+function cssSet(element, styleName, styleValue) {
+  if (typeof styleValue === 'number') {
+    styleValue = styleValue.toString() + 'px';
+  }
+  element.style[styleName] = styleValue;
+  return element;
+}
+
+function cssMultiSet(element, obj) {
+  for (var key in obj) {
+    var val = obj[key];
+    if (typeof val === 'number') {
+      val = val.toString() + 'px';
+    }
+    element.style[key] = val;
+  }
+  return element;
+}
+
+DOM.css = function (element, styleNameOrObject, styleValue) {
+  if (typeof styleNameOrObject === 'object') {
+    // multiple set with object
+    return cssMultiSet(element, styleNameOrObject);
+  } else {
+    if (typeof styleValue === 'undefined') {
+      return cssGet(element, styleNameOrObject);
+    } else {
+      return cssSet(element, styleNameOrObject, styleValue);
+    }
+  }
+};
+
+DOM.matches = function (element, query) {
+  if (typeof element.matches !== 'undefined') {
+    return element.matches(query);
+  } else {
+    if (typeof element.matchesSelector !== 'undefined') {
+      return element.matchesSelector(query);
+    } else if (typeof element.webkitMatchesSelector !== 'undefined') {
+      return element.webkitMatchesSelector(query);
+    } else if (typeof element.mozMatchesSelector !== 'undefined') {
+      return element.mozMatchesSelector(query);
+    } else if (typeof element.msMatchesSelector !== 'undefined') {
+      return element.msMatchesSelector(query);
+    }
+  }
+};
+
+DOM.remove = function (element) {
+  if (typeof element.remove !== 'undefined') {
+    element.remove();
+  } else {
+    if (element.parentNode) {
+      element.parentNode.removeChild(element);
+    }
+  }
+};
+
+DOM.queryChildren = function (element, selector) {
+  return Array.prototype.filter.call(element.childNodes, function (child) {
+    return DOM.matches(child, selector);
+  });
+};
+
+module.exports = DOM;
+
+},{}],4:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var EventElement = function (element) {
+  this.element = element;
+  this.events = {};
+};
+
+EventElement.prototype.bind = function (eventName, handler) {
+  if (typeof this.events[eventName] === 'undefined') {
+    this.events[eventName] = [];
+  }
+  this.events[eventName].push(handler);
+  this.element.addEventListener(eventName, handler, false);
+};
+
+EventElement.prototype.unbind = function (eventName, handler) {
+  var isHandlerProvided = (typeof handler !== 'undefined');
+  this.events[eventName] = this.events[eventName].filter(function (hdlr) {
+    if (isHandlerProvided && hdlr !== handler) {
+      return true;
+    }
+    this.element.removeEventListener(eventName, hdlr, false);
+    return false;
+  }, this);
+};
+
+EventElement.prototype.unbindAll = function () {
+  for (var name in this.events) {
+    this.unbind(name);
+  }
+};
+
+var EventManager = function () {
+  this.eventElements = [];
+};
+
+EventManager.prototype.eventElement = function (element) {
+  var ee = this.eventElements.filter(function (eventElement) {
+    return eventElement.element === element;
+  })[0];
+  if (typeof ee === 'undefined') {
+    ee = new EventElement(element);
+    this.eventElements.push(ee);
+  }
+  return ee;
+};
+
+EventManager.prototype.bind = function (element, eventName, handler) {
+  this.eventElement(element).bind(eventName, handler);
+};
+
+EventManager.prototype.unbind = function (element, eventName, handler) {
+  this.eventElement(element).unbind(eventName, handler);
+};
+
+EventManager.prototype.unbindAll = function () {
+  for (var i = 0; i < this.eventElements.length; i++) {
+    this.eventElements[i].unbindAll();
+  }
+};
+
+EventManager.prototype.once = function (element, eventName, handler) {
+  var ee = this.eventElement(element);
+  var onceHandler = function (e) {
+    ee.unbind(eventName, onceHandler);
+    handler(e);
+  };
+  ee.bind(eventName, onceHandler);
+};
+
+module.exports = EventManager;
+
+},{}],5:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+module.exports = (function () {
+  function s4() {
+    return Math.floor((1 + Math.random()) * 0x10000)
+               .toString(16)
+               .substring(1);
+  }
+  return function () {
+    return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
+           s4() + '-' + s4() + s4() + s4();
+  };
+})();
+
+},{}],6:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var cls = require('./class')
+  , d = require('./dom');
+
+exports.toInt = function (x) {
+  return parseInt(x, 10) || 0;
+};
+
+exports.clone = function (obj) {
+  if (obj === null) {
+    return null;
+  } else if (typeof obj === 'object') {
+    var result = {};
+    for (var key in obj) {
+      result[key] = this.clone(obj[key]);
+    }
+    return result;
+  } else {
+    return obj;
+  }
+};
+
+exports.extend = function (original, source) {
+  var result = this.clone(original);
+  for (var key in source) {
+    result[key] = this.clone(source[key]);
+  }
+  return result;
+};
+
+exports.isEditable = function (el) {
+  return d.matches(el, "input,[contenteditable]") ||
+         d.matches(el, "select,[contenteditable]") ||
+         d.matches(el, "textarea,[contenteditable]") ||
+         d.matches(el, "button,[contenteditable]");
+};
+
+exports.removePsClasses = function (element) {
+  var clsList = cls.list(element);
+  for (var i = 0; i < clsList.length; i++) {
+    var className = clsList[i];
+    if (className.indexOf('ps-') === 0) {
+      cls.remove(element, className);
+    }
+  }
+};
+
+exports.outerWidth = function (element) {
+  return this.toInt(d.css(element, 'width')) +
+         this.toInt(d.css(element, 'paddingLeft')) +
+         this.toInt(d.css(element, 'paddingRight')) +
+         this.toInt(d.css(element, 'borderLeftWidth')) +
+         this.toInt(d.css(element, 'borderRightWidth'));
+};
+
+exports.startScrolling = function (element, axis) {
+  cls.add(element, 'ps-in-scrolling');
+  if (typeof axis !== 'undefined') {
+    cls.add(element, 'ps-' + axis);
+  } else {
+    cls.add(element, 'ps-x');
+    cls.add(element, 'ps-y');
+  }
+};
+
+exports.stopScrolling = function (element, axis) {
+  cls.remove(element, 'ps-in-scrolling');
+  if (typeof axis !== 'undefined') {
+    cls.remove(element, 'ps-' + axis);
+  } else {
+    cls.remove(element, 'ps-x');
+    cls.remove(element, 'ps-y');
+  }
+};
+
+exports.env = {
+  isWebKit: 'WebkitAppearance' in document.documentElement.style,
+  supportsTouch: (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch),
+  supportsIePointer: window.navigator.msMaxTouchPoints !== null
+};
+
+},{"./class":2,"./dom":3}],7:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var destroy = require('./plugin/destroy')
+  , initialize = require('./plugin/initialize')
+  , update = require('./plugin/update');
+
+module.exports = {
+  initialize: initialize,
+  update: update,
+  destroy: destroy
+};
+
+},{"./plugin/destroy":9,"./plugin/initialize":17,"./plugin/update":20}],8:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+module.exports = {
+  wheelSpeed: 1,
+  wheelPropagation: false,
+  swipePropagation: true,
+  minScrollbarLength: null,
+  maxScrollbarLength: null,
+  useBothWheelAxes: false,
+  useKeyboard: true,
+  suppressScrollX: false,
+  suppressScrollY: false,
+  scrollXMarginOffset: 0,
+  scrollYMarginOffset: 0,
+  stopPropagationOnClick: true
+};
+
+},{}],9:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var d = require('../lib/dom')
+  , h = require('../lib/helper')
+  , instances = require('./instances');
+
+module.exports = function (element) {
+  var i = instances.get(element);
+
+  if (!i) {
+    return;
+  }
+
+  i.event.unbindAll();
+  d.remove(i.scrollbarX);
+  d.remove(i.scrollbarY);
+  d.remove(i.scrollbarXRail);
+  d.remove(i.scrollbarYRail);
+  h.removePsClasses(element);
+
+  instances.remove(element);
+};
+
+},{"../lib/dom":3,"../lib/helper":6,"./instances":18}],10:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var h = require('../../lib/helper')
+  , instances = require('../instances')
+  , updateGeometry = require('../update-geometry');
+
+function bindClickRailHandler(element, i) {
+  function pageOffset(el) {
+    return el.getBoundingClientRect();
+  }
+  var stopPropagation = window.Event.prototype.stopPropagation.bind;
+
+  if (i.settings.stopPropagationOnClick) {
+    i.event.bind(i.scrollbarY, 'click', stopPropagation);
+  }
+  i.event.bind(i.scrollbarYRail, 'click', function (e) {
+    var halfOfScrollbarLength = h.toInt(i.scrollbarYHeight / 2);
+    var positionTop = i.railYRatio * (e.pageY - window.scrollY - pageOffset(i.scrollbarYRail).top - halfOfScrollbarLength);
+    var maxPositionTop = i.railYRatio * (i.railYHeight - i.scrollbarYHeight);
+    var positionRatio = positionTop / maxPositionTop;
+
+    if (positionRatio < 0) {
+      positionRatio = 0;
+    } else if (positionRatio > 1) {
+      positionRatio = 1;
+    }
+
+    element.scrollTop = (i.contentHeight - i.containerHeight) * positionRatio;
+    updateGeometry(element);
+
+    e.stopPropagation();
+  });
+
+  if (i.settings.stopPropagationOnClick) {
+    i.event.bind(i.scrollbarX, 'click', stopPropagation);
+  }
+  i.event.bind(i.scrollbarXRail, 'click', function (e) {
+    var halfOfScrollbarLength = h.toInt(i.scrollbarXWidth / 2);
+    var positionLeft = i.railXRatio * (e.pageX - window.scrollX - pageOffset(i.scrollbarXRail).left - halfOfScrollbarLength);
+    var maxPositionLeft = i.railXRatio * (i.railXWidth - i.scrollbarXWidth);
+    var positionRatio = positionLeft / maxPositionLeft;
+
+    if (positionRatio < 0) {
+      positionRatio = 0;
+    } else if (positionRatio > 1) {
+      positionRatio = 1;
+    }
+
+    element.scrollLeft = ((i.contentWidth - i.containerWidth) * positionRatio) - i.negativeScrollAdjustment;
+    updateGeometry(element);
+
+    e.stopPropagation();
+  });
+}
+
+module.exports = function (element) {
+  var i = instances.get(element);
+  bindClickRailHandler(element, i);
+};
+
+},{"../../lib/helper":6,"../instances":18,"../update-geometry":19}],11:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var d = require('../../lib/dom')
+  , h = require('../../lib/helper')
+  , instances = require('../instances')
+  , updateGeometry = require('../update-geometry');
+
+function bindMouseScrollXHandler(element, i) {
+  var currentLeft = null;
+  var currentPageX = null;
+
+  function updateScrollLeft(deltaX) {
+    var newLeft = currentLeft + (deltaX * i.railXRatio);
+    var maxLeft = i.scrollbarXRail.getBoundingClientRect().left + (i.railXRatio * (i.railXWidth - i.scrollbarXWidth));
+
+    if (newLeft < 0) {
+      i.scrollbarXLeft = 0;
+    } else if (newLeft > maxLeft) {
+      i.scrollbarXLeft = maxLeft;
+    } else {
+      i.scrollbarXLeft = newLeft;
+    }
+
+    var scrollLeft = h.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - (i.railXRatio * i.scrollbarXWidth))) - i.negativeScrollAdjustment;
+    element.scrollLeft = scrollLeft;
+  }
+
+  var mouseMoveHandler = function (e) {
+    updateScrollLeft(e.pageX - currentPageX);
+    updateGeometry(element);
+    e.stopPropagation();
+    e.preventDefault();
+  };
+
+  var mouseUpHandler = function () {
+    h.stopScrolling(element, 'x');
+    i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+  };
+
+  i.event.bind(i.scrollbarX, 'mousedown', function (e) {
+    currentPageX = e.pageX;
+    currentLeft = h.toInt(d.css(i.scrollbarX, 'left')) * i.railXRatio;
+    h.startScrolling(element, 'x');
+
+    i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+    i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
+
+    e.stopPropagation();
+    e.preventDefault();
+  });
+}
+
+function bindMouseScrollYHandler(element, i) {
+  var currentTop = null;
+  var currentPageY = null;
+
+  function updateScrollTop(deltaY) {
+    var newTop = currentTop + (deltaY * i.railYRatio);
+    var maxTop = i.scrollbarYRail.getBoundingClientRect().top + (i.railYRatio * (i.railYHeight - i.scrollbarYHeight));
+
+    if (newTop < 0) {
+      i.scrollbarYTop = 0;
+    } else if (newTop > maxTop) {
+      i.scrollbarYTop = maxTop;
+    } else {
+      i.scrollbarYTop = newTop;
+    }
+
+    var scrollTop = h.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - (i.railYRatio * i.scrollbarYHeight)));
+    element.scrollTop = scrollTop;
+  }
+
+  var mouseMoveHandler = function (e) {
+    updateScrollTop(e.pageY - currentPageY);
+    updateGeometry(element);
+    e.stopPropagation();
+    e.preventDefault();
+  };
+
+  var mouseUpHandler = function () {
+    h.stopScrolling(element, 'y');
+    i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+  };
+
+  i.event.bind(i.scrollbarY, 'mousedown', function (e) {
+    currentPageY = e.pageY;
+    currentTop = h.toInt(d.css(i.scrollbarY, 'top')) * i.railYRatio;
+    h.startScrolling(element, 'y');
+
+    i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+    i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
+
+    e.stopPropagation();
+    e.preventDefault();
+  });
+}
+
+module.exports = function (element) {
+  var i = instances.get(element);
+  bindMouseScrollXHandler(element, i);
+  bindMouseScrollYHandler(element, i);
+};
+
+},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19}],12:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var h = require('../../lib/helper')
+  , instances = require('../instances')
+  , updateGeometry = require('../update-geometry');
+
+function bindKeyboardHandler(element, i) {
+  var hovered = false;
+  i.event.bind(element, 'mouseenter', function () {
+    hovered = true;
+  });
+  i.event.bind(element, 'mouseleave', function () {
+    hovered = false;
+  });
+
+  var shouldPrevent = false;
+  function shouldPreventDefault(deltaX, deltaY) {
+    var scrollTop = element.scrollTop;
+    if (deltaX === 0) {
+      if (!i.scrollbarYActive) {
+        return false;
+      }
+      if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)) {
+        return !i.settings.wheelPropagation;
+      }
+    }
+
+    var scrollLeft = element.scrollLeft;
+    if (deltaY === 0) {
+      if (!i.scrollbarXActive) {
+        return false;
+      }
+      if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)) {
+        return !i.settings.wheelPropagation;
+      }
+    }
+    return true;
+  }
+
+  i.event.bind(i.ownerDocument, 'keydown', function (e) {
+    if (e.isDefaultPrevented && e.isDefaultPrevented()) {
+      return;
+    }
+
+    if (!hovered) {
+      return;
+    }
+
+    var activeElement = document.activeElement ? document.activeElement : i.ownerDocument.activeElement;
+    if (activeElement) {
+      // go deeper if element is a webcomponent
+      while (activeElement.shadowRoot) {
+        activeElement = activeElement.shadowRoot.activeElement;
+      }
+      if (h.isEditable(activeElement)) {
+        return;
+      }
+    }
+
+    var deltaX = 0;
+    var deltaY = 0;
+
+    switch (e.which) {
+    case 37: // left
+      deltaX = -30;
+      break;
+    case 38: // up
+      deltaY = 30;
+      break;
+    case 39: // right
+      deltaX = 30;
+      break;
+    case 40: // down
+      deltaY = -30;
+      break;
+    case 33: // page up
+      deltaY = 90;
+      break;
+    case 32: // space bar
+      if (e.shiftKey) {
+        deltaY = 90;
+      } else {
+        deltaY = -90;
+      }
+      break;
+    case 34: // page down
+      deltaY = -90;
+      break;
+    case 35: // end
+      if (e.ctrlKey) {
+        deltaY = -i.contentHeight;
+      } else {
+        deltaY = -i.containerHeight;
+      }
+      break;
+    case 36: // home
+      if (e.ctrlKey) {
+        deltaY = element.scrollTop;
+      } else {
+        deltaY = i.containerHeight;
+      }
+      break;
+    default:
+      return;
+    }
+
+    element.scrollTop = element.scrollTop - deltaY;
+    element.scrollLeft = element.scrollLeft + deltaX;
+    updateGeometry(element);
+
+    shouldPrevent = shouldPreventDefault(deltaX, deltaY);
+    if (shouldPrevent) {
+      e.preventDefault();
+    }
+  });
+}
+
+module.exports = function (element) {
+  var i = instances.get(element);
+  bindKeyboardHandler(element, i);
+};
+
+},{"../../lib/helper":6,"../instances":18,"../update-geometry":19}],13:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var h = require('../../lib/helper')
+  , instances = require('../instances')
+  , updateGeometry = require('../update-geometry');
+
+function bindMouseWheelHandler(element, i) {
+  var shouldPrevent = false;
+
+  function shouldPreventDefault(deltaX, deltaY) {
+    var scrollTop = element.scrollTop;
+    if (deltaX === 0) {
+      if (!i.scrollbarYActive) {
+        return false;
+      }
+      if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)) {
+        return !i.settings.wheelPropagation;
+      }
+    }
+
+    var scrollLeft = element.scrollLeft;
+    if (deltaY === 0) {
+      if (!i.scrollbarXActive) {
+        return false;
+      }
+      if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)) {
+        return !i.settings.wheelPropagation;
+      }
+    }
+    return true;
+  }
+
+  function getDeltaFromEvent(e) {
+    var deltaX = e.deltaX;
+    var deltaY = -1 * e.deltaY;
+
+    if (typeof deltaX === "undefined" || typeof deltaY === "undefined") {
+      // OS X Safari
+      deltaX = -1 * e.wheelDeltaX / 6;
+      deltaY = e.wheelDeltaY / 6;
+    }
+
+    if (e.deltaMode && e.deltaMode === 1) {
+      // Firefox in deltaMode 1: Line scrolling
+      deltaX *= 10;
+      deltaY *= 10;
+    }
+
+    if (deltaX !== deltaX && deltaY !== deltaY/* NaN checks */) {
+      // IE in some mouse drivers
+      deltaX = 0;
+      deltaY = e.wheelDelta;
+    }
+
+    return [deltaX, deltaY];
+  }
+
+  function shouldBeConsumedByTextarea(deltaX, deltaY) {
+    var hoveredTextarea = element.querySelector('textarea:hover');
+    if (hoveredTextarea) {
+      var maxScrollTop = hoveredTextarea.scrollHeight - hoveredTextarea.clientHeight;
+      if (maxScrollTop > 0) {
+        if (!(hoveredTextarea.scrollTop === 0 && deltaY > 0) &&
+            !(hoveredTextarea.scrollTop === maxScrollTop && deltaY < 0)) {
+          return true;
+        }
+      }
+      var maxScrollLeft = hoveredTextarea.scrollLeft - hoveredTextarea.clientWidth;
+      if (maxScrollLeft > 0) {
+        if (!(hoveredTextarea.scrollLeft === 0 && deltaX < 0) &&
+            !(hoveredTextarea.scrollLeft === maxScrollLeft && deltaX > 0)) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  function mousewheelHandler(e) {
+    // FIXME: this is a quick fix for the select problem in FF and IE.
+    // If there comes an effective way to deal with the problem,
+    // this lines should be removed.
+    if (!h.env.isWebKit && element.querySelector('select:focus')) {
+      return;
+    }
+
+    var delta = getDeltaFromEvent(e);
+
+    var deltaX = delta[0];
+    var deltaY = delta[1];
+
+    if (shouldBeConsumedByTextarea(deltaX, deltaY)) {
+      return;
+    }
+
+    shouldPrevent = false;
+    if (!i.settings.useBothWheelAxes) {
+      // deltaX will only be used for horizontal scrolling and deltaY will
+      // only be used for vertical scrolling - this is the default
+      element.scrollTop = element.scrollTop - (deltaY * i.settings.wheelSpeed);
+      element.scrollLeft = element.scrollLeft + (deltaX * i.settings.wheelSpeed);
+    } else if (i.scrollbarYActive && !i.scrollbarXActive) {
+      // only vertical scrollbar is active and useBothWheelAxes option is
+      // active, so let's scroll vertical bar using both mouse wheel axes
+      if (deltaY) {
+        element.scrollTop = element.scrollTop - (deltaY * i.settings.wheelSpeed);
+      } else {
+        element.scrollTop = element.scrollTop + (deltaX * i.settings.wheelSpeed);
+      }
+      shouldPrevent = true;
+    } else if (i.scrollbarXActive && !i.scrollbarYActive) {
+      // useBothWheelAxes and only horizontal bar is active, so use both
+      // wheel axes for horizontal bar
+      if (deltaX) {
+        element.scrollLeft = element.scrollLeft + (deltaX * i.settings.wheelSpeed);
+      } else {
+        element.scrollLeft = element.scrollLeft - (deltaY * i.settings.wheelSpeed);
+      }
+      shouldPrevent = true;
+    }
+
+    updateGeometry(element);
+
+    shouldPrevent = (shouldPrevent || shouldPreventDefault(deltaX, deltaY));
+    if (shouldPrevent) {
+      e.stopPropagation();
+      e.preventDefault();
+    }
+  }
+
+  if (typeof window.onwheel !== "undefined") {
+    i.event.bind(element, 'wheel', mousewheelHandler);
+  } else if (typeof window.onmousewheel !== "undefined") {
+    i.event.bind(element, 'mousewheel', mousewheelHandler);
+  }
+}
+
+module.exports = function (element) {
+  var i = instances.get(element);
+  bindMouseWheelHandler(element, i);
+};
+
+},{"../../lib/helper":6,"../instances":18,"../update-geometry":19}],14:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var instances = require('../instances')
+  , updateGeometry = require('../update-geometry');
+
+function bindNativeScrollHandler(element, i) {
+  i.event.bind(element, 'scroll', function () {
+    updateGeometry(element);
+  });
+}
+
+module.exports = function (element) {
+  var i = instances.get(element);
+  bindNativeScrollHandler(element, i);
+};
+
+},{"../instances":18,"../update-geometry":19}],15:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var h = require('../../lib/helper')
+  , instances = require('../instances')
+  , updateGeometry = require('../update-geometry');
+
+function bindSelectionHandler(element, i) {
+  function getRangeNode() {
+    var selection = window.getSelection ? window.getSelection() :
+                    document.getSelection ? document.getSelection() : '';
+    if (selection.toString().length === 0) {
+      return null;
+    } else {
+      return selection.getRangeAt(0).commonAncestorContainer;
+    }
+  }
+
+  var scrollingLoop = null;
+  var scrollDiff = {top: 0, left: 0};
+  function startScrolling() {
+    if (!scrollingLoop) {
+      scrollingLoop = setInterval(function () {
+        if (!instances.get(element)) {
+          clearInterval(scrollingLoop);
+          return;
+        }
+
+        element.scrollTop = element.scrollTop + scrollDiff.top;
+        element.scrollLeft = element.scrollLeft + scrollDiff.left;
+        updateGeometry(element);
+      }, 50); // every .1 sec
+    }
+  }
+  function stopScrolling() {
+    if (scrollingLoop) {
+      clearInterval(scrollingLoop);
+      scrollingLoop = null;
+    }
+    h.stopScrolling(element);
+  }
+
+  var isSelected = false;
+  i.event.bind(i.ownerDocument, 'selectionchange', function () {
+    if (element.contains(getRangeNode())) {
+      isSelected = true;
+    } else {
+      isSelected = false;
+      stopScrolling();
+    }
+  });
+  i.event.bind(window, 'mouseup', function () {
+    if (isSelected) {
+      isSelected = false;
+      stopScrolling();
+    }
+  });
+
+  i.event.bind(window, 'mousemove', function (e) {
+    if (isSelected) {
+      var mousePosition = {x: e.pageX, y: e.pageY};
+      var containerGeometry = {
+        left: element.offsetLeft,
+        right: element.offsetLeft + element.offsetWidth,
+        top: element.offsetTop,
+        bottom: element.offsetTop + element.offsetHeight
+      };
+
+      if (mousePosition.x < containerGeometry.left + 3) {
+        scrollDiff.left = -5;
+        h.startScrolling(element, 'x');
+      } else if (mousePosition.x > containerGeometry.right - 3) {
+        scrollDiff.left = 5;
+        h.startScrolling(element, 'x');
+      } else {
+        scrollDiff.left = 0;
+      }
+
+      if (mousePosition.y < containerGeometry.top + 3) {
+        if (containerGeometry.top + 3 - mousePosition.y < 5) {
+          scrollDiff.top = -5;
+        } else {
+          scrollDiff.top = -20;
+        }
+        h.startScrolling(element, 'y');
+      } else if (mousePosition.y > containerGeometry.bottom - 3) {
+        if (mousePosition.y - containerGeometry.bottom + 3 < 5) {
+          scrollDiff.top = 5;
+        } else {
+          scrollDiff.top = 20;
+        }
+        h.startScrolling(element, 'y');
+      } else {
+        scrollDiff.top = 0;
+      }
+
+      if (scrollDiff.top === 0 && scrollDiff.left === 0) {
+        stopScrolling();
+      } else {
+        startScrolling();
+      }
+    }
+  });
+}
+
+module.exports = function (element) {
+  var i = instances.get(element);
+  bindSelectionHandler(element, i);
+};
+
+},{"../../lib/helper":6,"../instances":18,"../update-geometry":19}],16:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var instances = require('../instances')
+  , updateGeometry = require('../update-geometry');
+
+function bindTouchHandler(element, i, supportsTouch, supportsIePointer) {
+  function shouldPreventDefault(deltaX, deltaY) {
+    var scrollTop = element.scrollTop;
+    var scrollLeft = element.scrollLeft;
+    var magnitudeX = Math.abs(deltaX);
+    var magnitudeY = Math.abs(deltaY);
+
+    if (magnitudeY > magnitudeX) {
+      // user is perhaps trying to swipe up/down the page
+
+      if (((deltaY < 0) && (scrollTop === i.contentHeight - i.containerHeight)) ||
+          ((deltaY > 0) && (scrollTop === 0))) {
+        return !i.settings.swipePropagation;
+      }
+    } else if (magnitudeX > magnitudeY) {
+      // user is perhaps trying to swipe left/right across the page
+
+      if (((deltaX < 0) && (scrollLeft === i.contentWidth - i.containerWidth)) ||
+          ((deltaX > 0) && (scrollLeft === 0))) {
+        return !i.settings.swipePropagation;
+      }
+    }
+
+    return true;
+  }
+
+  function applyTouchMove(differenceX, differenceY) {
+    element.scrollTop = element.scrollTop - differenceY;
+    element.scrollLeft = element.scrollLeft - differenceX;
+
+    updateGeometry(element);
+  }
+
+  var startOffset = {};
+  var startTime = 0;
+  var speed = {};
+  var easingLoop = null;
+  var inGlobalTouch = false;
+  var inLocalTouch = false;
+
+  function globalTouchStart() {
+    inGlobalTouch = true;
+  }
+  function globalTouchEnd() {
+    inGlobalTouch = false;
+  }
+
+  function getTouch(e) {
+    if (e.targetTouches) {
+      return e.targetTouches[0];
+    } else {
+      // Maybe IE pointer
+      return e;
+    }
+  }
+  function shouldHandle(e) {
+    if (e.targetTouches && e.targetTouches.length === 1) {
+      return true;
+    }
+    if (e.pointerType && e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {
+      return true;
+    }
+    return false;
+  }
+  function touchStart(e) {
+    if (shouldHandle(e)) {
+      inLocalTouch = true;
+
+      var touch = getTouch(e);
+
+      startOffset.pageX = touch.pageX;
+      startOffset.pageY = touch.pageY;
+
+      startTime = (new Date()).getTime();
+
+      if (easingLoop !== null) {
+        clearInterval(easingLoop);
+      }
+
+      e.stopPropagation();
+    }
+  }
+  function touchMove(e) {
+    if (!inGlobalTouch && inLocalTouch && shouldHandle(e)) {
+      var touch = getTouch(e);
+
+      var currentOffset = {pageX: touch.pageX, pageY: touch.pageY};
+
+      var differenceX = currentOffset.pageX - startOffset.pageX;
+      var differenceY = currentOffset.pageY - startOffset.pageY;
+
+      applyTouchMove(differenceX, differenceY);
+      startOffset = currentOffset;
+
+      var currentTime = (new Date()).getTime();
+
+      var timeGap = currentTime - startTime;
+      if (timeGap > 0) {
+        speed.x = differenceX / timeGap;
+        speed.y = differenceY / timeGap;
+        startTime = currentTime;
+      }
+
+      if (shouldPreventDefault(differenceX, differenceY)) {
+        e.stopPropagation();
+        e.preventDefault();
+      }
+    }
+  }
+  function touchEnd() {
+    if (!inGlobalTouch && inLocalTouch) {
+      inLocalTouch = false;
+
+      clearInterval(easingLoop);
+      easingLoop = setInterval(function () {
+        if (!instances.get(element)) {
+          clearInterval(easingLoop);
+          return;
+        }
+
+        if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
+          clearInterval(easingLoop);
+          return;
+        }
+
+        applyTouchMove(speed.x * 30, speed.y * 30);
+
+        speed.x *= 0.8;
+        speed.y *= 0.8;
+      }, 10);
+    }
+  }
+
+  if (supportsTouch) {
+    i.event.bind(window, 'touchstart', globalTouchStart);
+    i.event.bind(window, 'touchend', globalTouchEnd);
+    i.event.bind(element, 'touchstart', touchStart);
+    i.event.bind(element, 'touchmove', touchMove);
+    i.event.bind(element, 'touchend', touchEnd);
+  }
+
+  if (supportsIePointer) {
+    if (window.PointerEvent) {
+      i.event.bind(window, 'pointerdown', globalTouchStart);
+      i.event.bind(window, 'pointerup', globalTouchEnd);
+      i.event.bind(element, 'pointerdown', touchStart);
+      i.event.bind(element, 'pointermove', touchMove);
+      i.event.bind(element, 'pointerup', touchEnd);
+    } else if (window.MSPointerEvent) {
+      i.event.bind(window, 'MSPointerDown', globalTouchStart);
+      i.event.bind(window, 'MSPointerUp', globalTouchEnd);
+      i.event.bind(element, 'MSPointerDown', touchStart);
+      i.event.bind(element, 'MSPointerMove', touchMove);
+      i.event.bind(element, 'MSPointerUp', touchEnd);
+    }
+  }
+}
+
+module.exports = function (element, supportsTouch, supportsIePointer) {
+  var i = instances.get(element);
+  bindTouchHandler(element, i, supportsTouch, supportsIePointer);
+};
+
+},{"../instances":18,"../update-geometry":19}],17:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var cls = require('../lib/class')
+  , h = require('../lib/helper')
+  , instances = require('./instances')
+  , updateGeometry = require('./update-geometry');
+
+// Handlers
+var clickRailHandler = require('./handler/click-rail')
+  , dragScrollbarHandler = require('./handler/drag-scrollbar')
+  , keyboardHandler = require('./handler/keyboard')
+  , mouseWheelHandler = require('./handler/mouse-wheel')
+  , nativeScrollHandler = require('./handler/native-scroll')
+  , selectionHandler = require('./handler/selection')
+  , touchHandler = require('./handler/touch');
+
+module.exports = function (element, userSettings) {
+  userSettings = typeof userSettings === 'object' ? userSettings : {};
+
+  cls.add(element, 'ps-container');
+
+  // Create a plugin instance.
+  var i = instances.add(element);
+
+  i.settings = h.extend(i.settings, userSettings);
+
+  clickRailHandler(element);
+  dragScrollbarHandler(element);
+  mouseWheelHandler(element);
+  nativeScrollHandler(element);
+  selectionHandler(element);
+
+  if (h.env.supportsTouch || h.env.supportsIePointer) {
+    touchHandler(element, h.env.supportsTouch, h.env.supportsIePointer);
+  }
+  if (i.settings.useKeyboard) {
+    keyboardHandler(element);
+  }
+
+  updateGeometry(element);
+};
+
+},{"../lib/class":2,"../lib/helper":6,"./handler/click-rail":10,"./handler/drag-scrollbar":11,"./handler/keyboard":12,"./handler/mouse-wheel":13,"./handler/native-scroll":14,"./handler/selection":15,"./handler/touch":16,"./instances":18,"./update-geometry":19}],18:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var d = require('../lib/dom')
+  , defaultSettings = require('./default-setting')
+  , EventManager = require('../lib/event-manager')
+  , guid = require('../lib/guid')
+  , h = require('../lib/helper');
+
+var instances = {};
+
+function Instance(element) {
+  var i = this;
+
+  i.settings = h.clone(defaultSettings);
+  i.containerWidth = null;
+  i.containerHeight = null;
+  i.contentWidth = null;
+  i.contentHeight = null;
+
+  i.isRtl = d.css(element, 'direction') === "rtl";
+  i.isNegativeScroll = (function () {
+    var originalScrollLeft = element.scrollLeft;
+    var result = null;
+    element.scrollLeft = -1;
+    result = element.scrollLeft < 0;
+    element.scrollLeft = originalScrollLeft;
+    return result;
+  })();
+  i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
+  i.event = new EventManager();
+  i.ownerDocument = element.ownerDocument || document;
+
+  i.scrollbarXRail = d.appendTo(d.e('div', 'ps-scrollbar-x-rail'), element);
+  i.scrollbarX = d.appendTo(d.e('div', 'ps-scrollbar-x'), i.scrollbarXRail);
+  i.scrollbarXActive = null;
+  i.scrollbarXWidth = null;
+  i.scrollbarXLeft = null;
+  i.scrollbarXBottom = h.toInt(d.css(i.scrollbarXRail, 'bottom'));
+  i.isScrollbarXUsingBottom = i.scrollbarXBottom === i.scrollbarXBottom; // !isNaN
+  i.scrollbarXTop = i.isScrollbarXUsingBottom ? null : h.toInt(d.css(i.scrollbarXRail, 'top'));
+  i.railBorderXWidth = h.toInt(d.css(i.scrollbarXRail, 'borderLeftWidth')) + h.toInt(d.css(i.scrollbarXRail, 'borderRightWidth'));
+  // Set rail to display:block to calculate margins
+  d.css(i.scrollbarXRail, 'display', 'block');
+  i.railXMarginWidth = h.toInt(d.css(i.scrollbarXRail, 'marginLeft')) + h.toInt(d.css(i.scrollbarXRail, 'marginRight'));
+  d.css(i.scrollbarXRail, 'display', '');
+  i.railXWidth = null;
+  i.railXRatio = null;
+
+  i.scrollbarYRail = d.appendTo(d.e('div', 'ps-scrollbar-y-rail'), element);
+  i.scrollbarY = d.appendTo(d.e('div', 'ps-scrollbar-y'), i.scrollbarYRail);
+  i.scrollbarYActive = null;
+  i.scrollbarYHeight = null;
+  i.scrollbarYTop = null;
+  i.scrollbarYRight = h.toInt(d.css(i.scrollbarYRail, 'right'));
+  i.isScrollbarYUsingRight = i.scrollbarYRight === i.scrollbarYRight; // !isNaN
+  i.scrollbarYLeft = i.isScrollbarYUsingRight ? null : h.toInt(d.css(i.scrollbarYRail, 'left'));
+  i.scrollbarYOuterWidth = i.isRtl ? h.outerWidth(i.scrollbarY) : null;
+  i.railBorderYWidth = h.toInt(d.css(i.scrollbarYRail, 'borderTopWidth')) + h.toInt(d.css(i.scrollbarYRail, 'borderBottomWidth'));
+  d.css(i.scrollbarYRail, 'display', 'block');
+  i.railYMarginHeight = h.toInt(d.css(i.scrollbarYRail, 'marginTop')) + h.toInt(d.css(i.scrollbarYRail, 'marginBottom'));
+  d.css(i.scrollbarYRail, 'display', '');
+  i.railYHeight = null;
+  i.railYRatio = null;
+}
+
+function getId(element) {
+  if (typeof element.dataset === 'undefined') {
+    return element.getAttribute('data-ps-id');
+  } else {
+    return element.dataset.psId;
+  }
+}
+
+function setId(element, id) {
+  if (typeof element.dataset === 'undefined') {
+    element.setAttribute('data-ps-id', id);
+  } else {
+    element.dataset.psId = id;
+  }
+}
+
+function removeId(element) {
+  if (typeof element.dataset === 'undefined') {
+    element.removeAttribute('data-ps-id');
+  } else {
+    delete element.dataset.psId;
+  }
+}
+
+exports.add = function (element) {
+  var newId = guid();
+  setId(element, newId);
+  instances[newId] = new Instance(element);
+  return instances[newId];
+};
+
+exports.remove = function (element) {
+  delete instances[getId(element)];
+  removeId(element);
+};
+
+exports.get = function (element) {
+  return instances[getId(element)];
+};
+
+},{"../lib/dom":3,"../lib/event-manager":4,"../lib/guid":5,"../lib/helper":6,"./default-setting":8}],19:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var cls = require('../lib/class')
+  , d = require('../lib/dom')
+  , h = require('../lib/helper')
+  , instances = require('./instances');
+
+function getThumbSize(i, thumbSize) {
+  if (i.settings.minScrollbarLength) {
+    thumbSize = Math.max(thumbSize, i.settings.minScrollbarLength);
+  }
+  if (i.settings.maxScrollbarLength) {
+    thumbSize = Math.min(thumbSize, i.settings.maxScrollbarLength);
+  }
+  return thumbSize;
+}
+
+function updateCss(element, i) {
+  var xRailOffset = {width: i.railXWidth};
+  if (i.isRtl) {
+    xRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth - i.contentWidth;
+  } else {
+    xRailOffset.left = element.scrollLeft;
+  }
+  if (i.isScrollbarXUsingBottom) {
+    xRailOffset.bottom = i.scrollbarXBottom - element.scrollTop;
+  } else {
+    xRailOffset.top = i.scrollbarXTop + element.scrollTop;
+  }
+  d.css(i.scrollbarXRail, xRailOffset);
+
+  var yRailOffset = {top: element.scrollTop, height: i.railYHeight};
+  if (i.isScrollbarYUsingRight) {
+    if (i.isRtl) {
+      yRailOffset.right = i.contentWidth - (i.negativeScrollAdjustment + element.scrollLeft) - i.scrollbarYRight - i.scrollbarYOuterWidth;
+    } else {
+      yRailOffset.right = i.scrollbarYRight - element.scrollLeft;
+    }
+  } else {
+    if (i.isRtl) {
+      yRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth * 2 - i.contentWidth - i.scrollbarYLeft - i.scrollbarYOuterWidth;
+    } else {
+      yRailOffset.left = i.scrollbarYLeft + element.scrollLeft;
+    }
+  }
+  d.css(i.scrollbarYRail, yRailOffset);
+
+  d.css(i.scrollbarX, {left: i.scrollbarXLeft, width: i.scrollbarXWidth - i.railBorderXWidth});
+  d.css(i.scrollbarY, {top: i.scrollbarYTop, height: i.scrollbarYHeight - i.railBorderYWidth});
+}
+
+module.exports = function (element) {
+  var i = instances.get(element);
+
+  i.containerWidth = element.clientWidth;
+  i.containerHeight = element.clientHeight;
+  i.contentWidth = element.scrollWidth;
+  i.contentHeight = element.scrollHeight;
+
+  var existingRails;
+  if (!element.contains(i.scrollbarXRail)) {
+    existingRails = d.queryChildren(element, '.ps-scrollbar-x-rail');
+    if (existingRails.length > 0) {
+      existingRails.forEach(function (rail) {
+        d.remove(rail);
+      });
+    }
+    d.appendTo(i.scrollbarXRail, element);
+  }
+  if (!element.contains(i.scrollbarYRail)) {
+    existingRails = d.queryChildren(element, '.ps-scrollbar-y-rail');
+    if (existingRails.length > 0) {
+      existingRails.forEach(function (rail) {
+        d.remove(rail);
+      });
+    }
+    d.appendTo(i.scrollbarYRail, element);
+  }
+
+  if (!i.settings.suppressScrollX && i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth) {
+    i.scrollbarXActive = true;
+    i.railXWidth = i.containerWidth - i.railXMarginWidth;
+    i.railXRatio = i.containerWidth / i.railXWidth;
+    i.scrollbarXWidth = getThumbSize(i, h.toInt(i.railXWidth * i.containerWidth / i.contentWidth));
+    i.scrollbarXLeft = h.toInt((i.negativeScrollAdjustment + element.scrollLeft) * (i.railXWidth - i.scrollbarXWidth) / (i.contentWidth - i.containerWidth));
+  } else {
+    i.scrollbarXActive = false;
+    i.scrollbarXWidth = 0;
+    i.scrollbarXLeft = 0;
+    element.scrollLeft = 0;
+  }
+
+  if (!i.settings.suppressScrollY && i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight) {
+    i.scrollbarYActive = true;
+    i.railYHeight = i.containerHeight - i.railYMarginHeight;
+    i.railYRatio = i.containerHeight / i.railYHeight;
+    i.scrollbarYHeight = getThumbSize(i, h.toInt(i.railYHeight * i.containerHeight / i.contentHeight));
+    i.scrollbarYTop = h.toInt(element.scrollTop * (i.railYHeight - i.scrollbarYHeight) / (i.contentHeight - i.containerHeight));
+  } else {
+    i.scrollbarYActive = false;
+    i.scrollbarYHeight = 0;
+    i.scrollbarYTop = 0;
+    element.scrollTop = 0;
+  }
+
+  if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) {
+    i.scrollbarXLeft = i.railXWidth - i.scrollbarXWidth;
+  }
+  if (i.scrollbarYTop >= i.railYHeight - i.scrollbarYHeight) {
+    i.scrollbarYTop = i.railYHeight - i.scrollbarYHeight;
+  }
+
+  updateCss(element, i);
+
+  cls[i.scrollbarXActive ? 'add' : 'remove'](element, 'ps-active-x');
+  cls[i.scrollbarYActive ? 'add' : 'remove'](element, 'ps-active-y');
+};
+
+},{"../lib/class":2,"../lib/dom":3,"../lib/helper":6,"./instances":18}],20:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var d = require('../lib/dom')
+  , h = require('../lib/helper')
+  , instances = require('./instances')
+  , updateGeometry = require('./update-geometry');
+
+module.exports = function (element) {
+  var i = instances.get(element);
+
+  if (!i) {
+    return;
+  }
+
+  // Recalcuate negative scrollLeft adjustment
+  i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
+
+  // Recalculate rail margins
+  d.css(i.scrollbarXRail, 'display', 'block');
+  d.css(i.scrollbarYRail, 'display', 'block');
+  i.railXMarginWidth = h.toInt(d.css(i.scrollbarXRail, 'marginLeft')) + h.toInt(d.css(i.scrollbarXRail, 'marginRight'));
+  i.railYMarginHeight = h.toInt(d.css(i.scrollbarYRail, 'marginTop')) + h.toInt(d.css(i.scrollbarYRail, 'marginBottom'));
+
+  // Hide scrollbars not to affect scrollWidth and scrollHeight
+  d.css(i.scrollbarXRail, 'display', 'none');
+  d.css(i.scrollbarYRail, 'display', 'none');
+
+  updateGeometry(element);
+
+  d.css(i.scrollbarXRail, 'display', '');
+  d.css(i.scrollbarYRail, 'display', '');
+};
+
+},{"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-geometry":19}]},{},[1]);

文件差异内容过多而无法显示
+ 1 - 0
jet/static/jet/vendor/perfect-scrollbar/js/perfect-scrollbar.jquery.min.js


+ 1463 - 0
jet/static/jet/vendor/perfect-scrollbar/js/perfect-scrollbar.js

@@ -0,0 +1,1463 @@
+/* perfect-scrollbar v0.6.5 */
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var ps = require('../main');
+
+if (typeof define === 'function' && define.amd) {
+  // AMD
+  define(ps);
+} else {
+  // Add to a global object.
+  window.PerfectScrollbar = ps;
+  if (typeof window.Ps === 'undefined') {
+    window.Ps = ps;
+  }
+}
+
+},{"../main":7}],2:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+function oldAdd(element, className) {
+  var classes = element.className.split(' ');
+  if (classes.indexOf(className) < 0) {
+    classes.push(className);
+  }
+  element.className = classes.join(' ');
+}
+
+function oldRemove(element, className) {
+  var classes = element.className.split(' ');
+  var idx = classes.indexOf(className);
+  if (idx >= 0) {
+    classes.splice(idx, 1);
+  }
+  element.className = classes.join(' ');
+}
+
+exports.add = function (element, className) {
+  if (element.classList) {
+    element.classList.add(className);
+  } else {
+    oldAdd(element, className);
+  }
+};
+
+exports.remove = function (element, className) {
+  if (element.classList) {
+    element.classList.remove(className);
+  } else {
+    oldRemove(element, className);
+  }
+};
+
+exports.list = function (element) {
+  if (element.classList) {
+    return element.classList;
+  } else {
+    return element.className.split(' ');
+  }
+};
+
+},{}],3:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var DOM = {};
+
+DOM.e = function (tagName, className) {
+  var element = document.createElement(tagName);
+  element.className = className;
+  return element;
+};
+
+DOM.appendTo = function (child, parent) {
+  parent.appendChild(child);
+  return child;
+};
+
+function cssGet(element, styleName) {
+  return window.getComputedStyle(element)[styleName];
+}
+
+function cssSet(element, styleName, styleValue) {
+  if (typeof styleValue === 'number') {
+    styleValue = styleValue.toString() + 'px';
+  }
+  element.style[styleName] = styleValue;
+  return element;
+}
+
+function cssMultiSet(element, obj) {
+  for (var key in obj) {
+    var val = obj[key];
+    if (typeof val === 'number') {
+      val = val.toString() + 'px';
+    }
+    element.style[key] = val;
+  }
+  return element;
+}
+
+DOM.css = function (element, styleNameOrObject, styleValue) {
+  if (typeof styleNameOrObject === 'object') {
+    // multiple set with object
+    return cssMultiSet(element, styleNameOrObject);
+  } else {
+    if (typeof styleValue === 'undefined') {
+      return cssGet(element, styleNameOrObject);
+    } else {
+      return cssSet(element, styleNameOrObject, styleValue);
+    }
+  }
+};
+
+DOM.matches = function (element, query) {
+  if (typeof element.matches !== 'undefined') {
+    return element.matches(query);
+  } else {
+    if (typeof element.matchesSelector !== 'undefined') {
+      return element.matchesSelector(query);
+    } else if (typeof element.webkitMatchesSelector !== 'undefined') {
+      return element.webkitMatchesSelector(query);
+    } else if (typeof element.mozMatchesSelector !== 'undefined') {
+      return element.mozMatchesSelector(query);
+    } else if (typeof element.msMatchesSelector !== 'undefined') {
+      return element.msMatchesSelector(query);
+    }
+  }
+};
+
+DOM.remove = function (element) {
+  if (typeof element.remove !== 'undefined') {
+    element.remove();
+  } else {
+    if (element.parentNode) {
+      element.parentNode.removeChild(element);
+    }
+  }
+};
+
+DOM.queryChildren = function (element, selector) {
+  return Array.prototype.filter.call(element.childNodes, function (child) {
+    return DOM.matches(child, selector);
+  });
+};
+
+module.exports = DOM;
+
+},{}],4:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var EventElement = function (element) {
+  this.element = element;
+  this.events = {};
+};
+
+EventElement.prototype.bind = function (eventName, handler) {
+  if (typeof this.events[eventName] === 'undefined') {
+    this.events[eventName] = [];
+  }
+  this.events[eventName].push(handler);
+  this.element.addEventListener(eventName, handler, false);
+};
+
+EventElement.prototype.unbind = function (eventName, handler) {
+  var isHandlerProvided = (typeof handler !== 'undefined');
+  this.events[eventName] = this.events[eventName].filter(function (hdlr) {
+    if (isHandlerProvided && hdlr !== handler) {
+      return true;
+    }
+    this.element.removeEventListener(eventName, hdlr, false);
+    return false;
+  }, this);
+};
+
+EventElement.prototype.unbindAll = function () {
+  for (var name in this.events) {
+    this.unbind(name);
+  }
+};
+
+var EventManager = function () {
+  this.eventElements = [];
+};
+
+EventManager.prototype.eventElement = function (element) {
+  var ee = this.eventElements.filter(function (eventElement) {
+    return eventElement.element === element;
+  })[0];
+  if (typeof ee === 'undefined') {
+    ee = new EventElement(element);
+    this.eventElements.push(ee);
+  }
+  return ee;
+};
+
+EventManager.prototype.bind = function (element, eventName, handler) {
+  this.eventElement(element).bind(eventName, handler);
+};
+
+EventManager.prototype.unbind = function (element, eventName, handler) {
+  this.eventElement(element).unbind(eventName, handler);
+};
+
+EventManager.prototype.unbindAll = function () {
+  for (var i = 0; i < this.eventElements.length; i++) {
+    this.eventElements[i].unbindAll();
+  }
+};
+
+EventManager.prototype.once = function (element, eventName, handler) {
+  var ee = this.eventElement(element);
+  var onceHandler = function (e) {
+    ee.unbind(eventName, onceHandler);
+    handler(e);
+  };
+  ee.bind(eventName, onceHandler);
+};
+
+module.exports = EventManager;
+
+},{}],5:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+module.exports = (function () {
+  function s4() {
+    return Math.floor((1 + Math.random()) * 0x10000)
+               .toString(16)
+               .substring(1);
+  }
+  return function () {
+    return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
+           s4() + '-' + s4() + s4() + s4();
+  };
+})();
+
+},{}],6:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var cls = require('./class')
+  , d = require('./dom');
+
+exports.toInt = function (x) {
+  return parseInt(x, 10) || 0;
+};
+
+exports.clone = function (obj) {
+  if (obj === null) {
+    return null;
+  } else if (typeof obj === 'object') {
+    var result = {};
+    for (var key in obj) {
+      result[key] = this.clone(obj[key]);
+    }
+    return result;
+  } else {
+    return obj;
+  }
+};
+
+exports.extend = function (original, source) {
+  var result = this.clone(original);
+  for (var key in source) {
+    result[key] = this.clone(source[key]);
+  }
+  return result;
+};
+
+exports.isEditable = function (el) {
+  return d.matches(el, "input,[contenteditable]") ||
+         d.matches(el, "select,[contenteditable]") ||
+         d.matches(el, "textarea,[contenteditable]") ||
+         d.matches(el, "button,[contenteditable]");
+};
+
+exports.removePsClasses = function (element) {
+  var clsList = cls.list(element);
+  for (var i = 0; i < clsList.length; i++) {
+    var className = clsList[i];
+    if (className.indexOf('ps-') === 0) {
+      cls.remove(element, className);
+    }
+  }
+};
+
+exports.outerWidth = function (element) {
+  return this.toInt(d.css(element, 'width')) +
+         this.toInt(d.css(element, 'paddingLeft')) +
+         this.toInt(d.css(element, 'paddingRight')) +
+         this.toInt(d.css(element, 'borderLeftWidth')) +
+         this.toInt(d.css(element, 'borderRightWidth'));
+};
+
+exports.startScrolling = function (element, axis) {
+  cls.add(element, 'ps-in-scrolling');
+  if (typeof axis !== 'undefined') {
+    cls.add(element, 'ps-' + axis);
+  } else {
+    cls.add(element, 'ps-x');
+    cls.add(element, 'ps-y');
+  }
+};
+
+exports.stopScrolling = function (element, axis) {
+  cls.remove(element, 'ps-in-scrolling');
+  if (typeof axis !== 'undefined') {
+    cls.remove(element, 'ps-' + axis);
+  } else {
+    cls.remove(element, 'ps-x');
+    cls.remove(element, 'ps-y');
+  }
+};
+
+exports.env = {
+  isWebKit: 'WebkitAppearance' in document.documentElement.style,
+  supportsTouch: (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch),
+  supportsIePointer: window.navigator.msMaxTouchPoints !== null
+};
+
+},{"./class":2,"./dom":3}],7:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var destroy = require('./plugin/destroy')
+  , initialize = require('./plugin/initialize')
+  , update = require('./plugin/update');
+
+module.exports = {
+  initialize: initialize,
+  update: update,
+  destroy: destroy
+};
+
+},{"./plugin/destroy":9,"./plugin/initialize":17,"./plugin/update":20}],8:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+module.exports = {
+  wheelSpeed: 1,
+  wheelPropagation: false,
+  swipePropagation: true,
+  minScrollbarLength: null,
+  maxScrollbarLength: null,
+  useBothWheelAxes: false,
+  useKeyboard: true,
+  suppressScrollX: false,
+  suppressScrollY: false,
+  scrollXMarginOffset: 0,
+  scrollYMarginOffset: 0,
+  stopPropagationOnClick: true
+};
+
+},{}],9:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var d = require('../lib/dom')
+  , h = require('../lib/helper')
+  , instances = require('./instances');
+
+module.exports = function (element) {
+  var i = instances.get(element);
+
+  if (!i) {
+    return;
+  }
+
+  i.event.unbindAll();
+  d.remove(i.scrollbarX);
+  d.remove(i.scrollbarY);
+  d.remove(i.scrollbarXRail);
+  d.remove(i.scrollbarYRail);
+  h.removePsClasses(element);
+
+  instances.remove(element);
+};
+
+},{"../lib/dom":3,"../lib/helper":6,"./instances":18}],10:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var h = require('../../lib/helper')
+  , instances = require('../instances')
+  , updateGeometry = require('../update-geometry');
+
+function bindClickRailHandler(element, i) {
+  function pageOffset(el) {
+    return el.getBoundingClientRect();
+  }
+  var stopPropagation = window.Event.prototype.stopPropagation.bind;
+
+  if (i.settings.stopPropagationOnClick) {
+    i.event.bind(i.scrollbarY, 'click', stopPropagation);
+  }
+  i.event.bind(i.scrollbarYRail, 'click', function (e) {
+    var halfOfScrollbarLength = h.toInt(i.scrollbarYHeight / 2);
+    var positionTop = i.railYRatio * (e.pageY - window.scrollY - pageOffset(i.scrollbarYRail).top - halfOfScrollbarLength);
+    var maxPositionTop = i.railYRatio * (i.railYHeight - i.scrollbarYHeight);
+    var positionRatio = positionTop / maxPositionTop;
+
+    if (positionRatio < 0) {
+      positionRatio = 0;
+    } else if (positionRatio > 1) {
+      positionRatio = 1;
+    }
+
+    element.scrollTop = (i.contentHeight - i.containerHeight) * positionRatio;
+    updateGeometry(element);
+
+    e.stopPropagation();
+  });
+
+  if (i.settings.stopPropagationOnClick) {
+    i.event.bind(i.scrollbarX, 'click', stopPropagation);
+  }
+  i.event.bind(i.scrollbarXRail, 'click', function (e) {
+    var halfOfScrollbarLength = h.toInt(i.scrollbarXWidth / 2);
+    var positionLeft = i.railXRatio * (e.pageX - window.scrollX - pageOffset(i.scrollbarXRail).left - halfOfScrollbarLength);
+    var maxPositionLeft = i.railXRatio * (i.railXWidth - i.scrollbarXWidth);
+    var positionRatio = positionLeft / maxPositionLeft;
+
+    if (positionRatio < 0) {
+      positionRatio = 0;
+    } else if (positionRatio > 1) {
+      positionRatio = 1;
+    }
+
+    element.scrollLeft = ((i.contentWidth - i.containerWidth) * positionRatio) - i.negativeScrollAdjustment;
+    updateGeometry(element);
+
+    e.stopPropagation();
+  });
+}
+
+module.exports = function (element) {
+  var i = instances.get(element);
+  bindClickRailHandler(element, i);
+};
+
+},{"../../lib/helper":6,"../instances":18,"../update-geometry":19}],11:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var d = require('../../lib/dom')
+  , h = require('../../lib/helper')
+  , instances = require('../instances')
+  , updateGeometry = require('../update-geometry');
+
+function bindMouseScrollXHandler(element, i) {
+  var currentLeft = null;
+  var currentPageX = null;
+
+  function updateScrollLeft(deltaX) {
+    var newLeft = currentLeft + (deltaX * i.railXRatio);
+    var maxLeft = i.scrollbarXRail.getBoundingClientRect().left + (i.railXRatio * (i.railXWidth - i.scrollbarXWidth));
+
+    if (newLeft < 0) {
+      i.scrollbarXLeft = 0;
+    } else if (newLeft > maxLeft) {
+      i.scrollbarXLeft = maxLeft;
+    } else {
+      i.scrollbarXLeft = newLeft;
+    }
+
+    var scrollLeft = h.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - (i.railXRatio * i.scrollbarXWidth))) - i.negativeScrollAdjustment;
+    element.scrollLeft = scrollLeft;
+  }
+
+  var mouseMoveHandler = function (e) {
+    updateScrollLeft(e.pageX - currentPageX);
+    updateGeometry(element);
+    e.stopPropagation();
+    e.preventDefault();
+  };
+
+  var mouseUpHandler = function () {
+    h.stopScrolling(element, 'x');
+    i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+  };
+
+  i.event.bind(i.scrollbarX, 'mousedown', function (e) {
+    currentPageX = e.pageX;
+    currentLeft = h.toInt(d.css(i.scrollbarX, 'left')) * i.railXRatio;
+    h.startScrolling(element, 'x');
+
+    i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+    i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
+
+    e.stopPropagation();
+    e.preventDefault();
+  });
+}
+
+function bindMouseScrollYHandler(element, i) {
+  var currentTop = null;
+  var currentPageY = null;
+
+  function updateScrollTop(deltaY) {
+    var newTop = currentTop + (deltaY * i.railYRatio);
+    var maxTop = i.scrollbarYRail.getBoundingClientRect().top + (i.railYRatio * (i.railYHeight - i.scrollbarYHeight));
+
+    if (newTop < 0) {
+      i.scrollbarYTop = 0;
+    } else if (newTop > maxTop) {
+      i.scrollbarYTop = maxTop;
+    } else {
+      i.scrollbarYTop = newTop;
+    }
+
+    var scrollTop = h.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - (i.railYRatio * i.scrollbarYHeight)));
+    element.scrollTop = scrollTop;
+  }
+
+  var mouseMoveHandler = function (e) {
+    updateScrollTop(e.pageY - currentPageY);
+    updateGeometry(element);
+    e.stopPropagation();
+    e.preventDefault();
+  };
+
+  var mouseUpHandler = function () {
+    h.stopScrolling(element, 'y');
+    i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+  };
+
+  i.event.bind(i.scrollbarY, 'mousedown', function (e) {
+    currentPageY = e.pageY;
+    currentTop = h.toInt(d.css(i.scrollbarY, 'top')) * i.railYRatio;
+    h.startScrolling(element, 'y');
+
+    i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+    i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
+
+    e.stopPropagation();
+    e.preventDefault();
+  });
+}
+
+module.exports = function (element) {
+  var i = instances.get(element);
+  bindMouseScrollXHandler(element, i);
+  bindMouseScrollYHandler(element, i);
+};
+
+},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19}],12:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var h = require('../../lib/helper')
+  , instances = require('../instances')
+  , updateGeometry = require('../update-geometry');
+
+function bindKeyboardHandler(element, i) {
+  var hovered = false;
+  i.event.bind(element, 'mouseenter', function () {
+    hovered = true;
+  });
+  i.event.bind(element, 'mouseleave', function () {
+    hovered = false;
+  });
+
+  var shouldPrevent = false;
+  function shouldPreventDefault(deltaX, deltaY) {
+    var scrollTop = element.scrollTop;
+    if (deltaX === 0) {
+      if (!i.scrollbarYActive) {
+        return false;
+      }
+      if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)) {
+        return !i.settings.wheelPropagation;
+      }
+    }
+
+    var scrollLeft = element.scrollLeft;
+    if (deltaY === 0) {
+      if (!i.scrollbarXActive) {
+        return false;
+      }
+      if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)) {
+        return !i.settings.wheelPropagation;
+      }
+    }
+    return true;
+  }
+
+  i.event.bind(i.ownerDocument, 'keydown', function (e) {
+    if (e.isDefaultPrevented && e.isDefaultPrevented()) {
+      return;
+    }
+
+    if (!hovered) {
+      return;
+    }
+
+    var activeElement = document.activeElement ? document.activeElement : i.ownerDocument.activeElement;
+    if (activeElement) {
+      // go deeper if element is a webcomponent
+      while (activeElement.shadowRoot) {
+        activeElement = activeElement.shadowRoot.activeElement;
+      }
+      if (h.isEditable(activeElement)) {
+        return;
+      }
+    }
+
+    var deltaX = 0;
+    var deltaY = 0;
+
+    switch (e.which) {
+    case 37: // left
+      deltaX = -30;
+      break;
+    case 38: // up
+      deltaY = 30;
+      break;
+    case 39: // right
+      deltaX = 30;
+      break;
+    case 40: // down
+      deltaY = -30;
+      break;
+    case 33: // page up
+      deltaY = 90;
+      break;
+    case 32: // space bar
+      if (e.shiftKey) {
+        deltaY = 90;
+      } else {
+        deltaY = -90;
+      }
+      break;
+    case 34: // page down
+      deltaY = -90;
+      break;
+    case 35: // end
+      if (e.ctrlKey) {
+        deltaY = -i.contentHeight;
+      } else {
+        deltaY = -i.containerHeight;
+      }
+      break;
+    case 36: // home
+      if (e.ctrlKey) {
+        deltaY = element.scrollTop;
+      } else {
+        deltaY = i.containerHeight;
+      }
+      break;
+    default:
+      return;
+    }
+
+    element.scrollTop = element.scrollTop - deltaY;
+    element.scrollLeft = element.scrollLeft + deltaX;
+    updateGeometry(element);
+
+    shouldPrevent = shouldPreventDefault(deltaX, deltaY);
+    if (shouldPrevent) {
+      e.preventDefault();
+    }
+  });
+}
+
+module.exports = function (element) {
+  var i = instances.get(element);
+  bindKeyboardHandler(element, i);
+};
+
+},{"../../lib/helper":6,"../instances":18,"../update-geometry":19}],13:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var h = require('../../lib/helper')
+  , instances = require('../instances')
+  , updateGeometry = require('../update-geometry');
+
+function bindMouseWheelHandler(element, i) {
+  var shouldPrevent = false;
+
+  function shouldPreventDefault(deltaX, deltaY) {
+    var scrollTop = element.scrollTop;
+    if (deltaX === 0) {
+      if (!i.scrollbarYActive) {
+        return false;
+      }
+      if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)) {
+        return !i.settings.wheelPropagation;
+      }
+    }
+
+    var scrollLeft = element.scrollLeft;
+    if (deltaY === 0) {
+      if (!i.scrollbarXActive) {
+        return false;
+      }
+      if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)) {
+        return !i.settings.wheelPropagation;
+      }
+    }
+    return true;
+  }
+
+  function getDeltaFromEvent(e) {
+    var deltaX = e.deltaX;
+    var deltaY = -1 * e.deltaY;
+
+    if (typeof deltaX === "undefined" || typeof deltaY === "undefined") {
+      // OS X Safari
+      deltaX = -1 * e.wheelDeltaX / 6;
+      deltaY = e.wheelDeltaY / 6;
+    }
+
+    if (e.deltaMode && e.deltaMode === 1) {
+      // Firefox in deltaMode 1: Line scrolling
+      deltaX *= 10;
+      deltaY *= 10;
+    }
+
+    if (deltaX !== deltaX && deltaY !== deltaY/* NaN checks */) {
+      // IE in some mouse drivers
+      deltaX = 0;
+      deltaY = e.wheelDelta;
+    }
+
+    return [deltaX, deltaY];
+  }
+
+  function shouldBeConsumedByTextarea(deltaX, deltaY) {
+    var hoveredTextarea = element.querySelector('textarea:hover');
+    if (hoveredTextarea) {
+      var maxScrollTop = hoveredTextarea.scrollHeight - hoveredTextarea.clientHeight;
+      if (maxScrollTop > 0) {
+        if (!(hoveredTextarea.scrollTop === 0 && deltaY > 0) &&
+            !(hoveredTextarea.scrollTop === maxScrollTop && deltaY < 0)) {
+          return true;
+        }
+      }
+      var maxScrollLeft = hoveredTextarea.scrollLeft - hoveredTextarea.clientWidth;
+      if (maxScrollLeft > 0) {
+        if (!(hoveredTextarea.scrollLeft === 0 && deltaX < 0) &&
+            !(hoveredTextarea.scrollLeft === maxScrollLeft && deltaX > 0)) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  function mousewheelHandler(e) {
+    // FIXME: this is a quick fix for the select problem in FF and IE.
+    // If there comes an effective way to deal with the problem,
+    // this lines should be removed.
+    if (!h.env.isWebKit && element.querySelector('select:focus')) {
+      return;
+    }
+
+    var delta = getDeltaFromEvent(e);
+
+    var deltaX = delta[0];
+    var deltaY = delta[1];
+
+    if (shouldBeConsumedByTextarea(deltaX, deltaY)) {
+      return;
+    }
+
+    shouldPrevent = false;
+    if (!i.settings.useBothWheelAxes) {
+      // deltaX will only be used for horizontal scrolling and deltaY will
+      // only be used for vertical scrolling - this is the default
+      element.scrollTop = element.scrollTop - (deltaY * i.settings.wheelSpeed);
+      element.scrollLeft = element.scrollLeft + (deltaX * i.settings.wheelSpeed);
+    } else if (i.scrollbarYActive && !i.scrollbarXActive) {
+      // only vertical scrollbar is active and useBothWheelAxes option is
+      // active, so let's scroll vertical bar using both mouse wheel axes
+      if (deltaY) {
+        element.scrollTop = element.scrollTop - (deltaY * i.settings.wheelSpeed);
+      } else {
+        element.scrollTop = element.scrollTop + (deltaX * i.settings.wheelSpeed);
+      }
+      shouldPrevent = true;
+    } else if (i.scrollbarXActive && !i.scrollbarYActive) {
+      // useBothWheelAxes and only horizontal bar is active, so use both
+      // wheel axes for horizontal bar
+      if (deltaX) {
+        element.scrollLeft = element.scrollLeft + (deltaX * i.settings.wheelSpeed);
+      } else {
+        element.scrollLeft = element.scrollLeft - (deltaY * i.settings.wheelSpeed);
+      }
+      shouldPrevent = true;
+    }
+
+    updateGeometry(element);
+
+    shouldPrevent = (shouldPrevent || shouldPreventDefault(deltaX, deltaY));
+    if (shouldPrevent) {
+      e.stopPropagation();
+      e.preventDefault();
+    }
+  }
+
+  if (typeof window.onwheel !== "undefined") {
+    i.event.bind(element, 'wheel', mousewheelHandler);
+  } else if (typeof window.onmousewheel !== "undefined") {
+    i.event.bind(element, 'mousewheel', mousewheelHandler);
+  }
+}
+
+module.exports = function (element) {
+  var i = instances.get(element);
+  bindMouseWheelHandler(element, i);
+};
+
+},{"../../lib/helper":6,"../instances":18,"../update-geometry":19}],14:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var instances = require('../instances')
+  , updateGeometry = require('../update-geometry');
+
+function bindNativeScrollHandler(element, i) {
+  i.event.bind(element, 'scroll', function () {
+    updateGeometry(element);
+  });
+}
+
+module.exports = function (element) {
+  var i = instances.get(element);
+  bindNativeScrollHandler(element, i);
+};
+
+},{"../instances":18,"../update-geometry":19}],15:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var h = require('../../lib/helper')
+  , instances = require('../instances')
+  , updateGeometry = require('../update-geometry');
+
+function bindSelectionHandler(element, i) {
+  function getRangeNode() {
+    var selection = window.getSelection ? window.getSelection() :
+                    document.getSelection ? document.getSelection() : '';
+    if (selection.toString().length === 0) {
+      return null;
+    } else {
+      return selection.getRangeAt(0).commonAncestorContainer;
+    }
+  }
+
+  var scrollingLoop = null;
+  var scrollDiff = {top: 0, left: 0};
+  function startScrolling() {
+    if (!scrollingLoop) {
+      scrollingLoop = setInterval(function () {
+        if (!instances.get(element)) {
+          clearInterval(scrollingLoop);
+          return;
+        }
+
+        element.scrollTop = element.scrollTop + scrollDiff.top;
+        element.scrollLeft = element.scrollLeft + scrollDiff.left;
+        updateGeometry(element);
+      }, 50); // every .1 sec
+    }
+  }
+  function stopScrolling() {
+    if (scrollingLoop) {
+      clearInterval(scrollingLoop);
+      scrollingLoop = null;
+    }
+    h.stopScrolling(element);
+  }
+
+  var isSelected = false;
+  i.event.bind(i.ownerDocument, 'selectionchange', function () {
+    if (element.contains(getRangeNode())) {
+      isSelected = true;
+    } else {
+      isSelected = false;
+      stopScrolling();
+    }
+  });
+  i.event.bind(window, 'mouseup', function () {
+    if (isSelected) {
+      isSelected = false;
+      stopScrolling();
+    }
+  });
+
+  i.event.bind(window, 'mousemove', function (e) {
+    if (isSelected) {
+      var mousePosition = {x: e.pageX, y: e.pageY};
+      var containerGeometry = {
+        left: element.offsetLeft,
+        right: element.offsetLeft + element.offsetWidth,
+        top: element.offsetTop,
+        bottom: element.offsetTop + element.offsetHeight
+      };
+
+      if (mousePosition.x < containerGeometry.left + 3) {
+        scrollDiff.left = -5;
+        h.startScrolling(element, 'x');
+      } else if (mousePosition.x > containerGeometry.right - 3) {
+        scrollDiff.left = 5;
+        h.startScrolling(element, 'x');
+      } else {
+        scrollDiff.left = 0;
+      }
+
+      if (mousePosition.y < containerGeometry.top + 3) {
+        if (containerGeometry.top + 3 - mousePosition.y < 5) {
+          scrollDiff.top = -5;
+        } else {
+          scrollDiff.top = -20;
+        }
+        h.startScrolling(element, 'y');
+      } else if (mousePosition.y > containerGeometry.bottom - 3) {
+        if (mousePosition.y - containerGeometry.bottom + 3 < 5) {
+          scrollDiff.top = 5;
+        } else {
+          scrollDiff.top = 20;
+        }
+        h.startScrolling(element, 'y');
+      } else {
+        scrollDiff.top = 0;
+      }
+
+      if (scrollDiff.top === 0 && scrollDiff.left === 0) {
+        stopScrolling();
+      } else {
+        startScrolling();
+      }
+    }
+  });
+}
+
+module.exports = function (element) {
+  var i = instances.get(element);
+  bindSelectionHandler(element, i);
+};
+
+},{"../../lib/helper":6,"../instances":18,"../update-geometry":19}],16:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var instances = require('../instances')
+  , updateGeometry = require('../update-geometry');
+
+function bindTouchHandler(element, i, supportsTouch, supportsIePointer) {
+  function shouldPreventDefault(deltaX, deltaY) {
+    var scrollTop = element.scrollTop;
+    var scrollLeft = element.scrollLeft;
+    var magnitudeX = Math.abs(deltaX);
+    var magnitudeY = Math.abs(deltaY);
+
+    if (magnitudeY > magnitudeX) {
+      // user is perhaps trying to swipe up/down the page
+
+      if (((deltaY < 0) && (scrollTop === i.contentHeight - i.containerHeight)) ||
+          ((deltaY > 0) && (scrollTop === 0))) {
+        return !i.settings.swipePropagation;
+      }
+    } else if (magnitudeX > magnitudeY) {
+      // user is perhaps trying to swipe left/right across the page
+
+      if (((deltaX < 0) && (scrollLeft === i.contentWidth - i.containerWidth)) ||
+          ((deltaX > 0) && (scrollLeft === 0))) {
+        return !i.settings.swipePropagation;
+      }
+    }
+
+    return true;
+  }
+
+  function applyTouchMove(differenceX, differenceY) {
+    element.scrollTop = element.scrollTop - differenceY;
+    element.scrollLeft = element.scrollLeft - differenceX;
+
+    updateGeometry(element);
+  }
+
+  var startOffset = {};
+  var startTime = 0;
+  var speed = {};
+  var easingLoop = null;
+  var inGlobalTouch = false;
+  var inLocalTouch = false;
+
+  function globalTouchStart() {
+    inGlobalTouch = true;
+  }
+  function globalTouchEnd() {
+    inGlobalTouch = false;
+  }
+
+  function getTouch(e) {
+    if (e.targetTouches) {
+      return e.targetTouches[0];
+    } else {
+      // Maybe IE pointer
+      return e;
+    }
+  }
+  function shouldHandle(e) {
+    if (e.targetTouches && e.targetTouches.length === 1) {
+      return true;
+    }
+    if (e.pointerType && e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {
+      return true;
+    }
+    return false;
+  }
+  function touchStart(e) {
+    if (shouldHandle(e)) {
+      inLocalTouch = true;
+
+      var touch = getTouch(e);
+
+      startOffset.pageX = touch.pageX;
+      startOffset.pageY = touch.pageY;
+
+      startTime = (new Date()).getTime();
+
+      if (easingLoop !== null) {
+        clearInterval(easingLoop);
+      }
+
+      e.stopPropagation();
+    }
+  }
+  function touchMove(e) {
+    if (!inGlobalTouch && inLocalTouch && shouldHandle(e)) {
+      var touch = getTouch(e);
+
+      var currentOffset = {pageX: touch.pageX, pageY: touch.pageY};
+
+      var differenceX = currentOffset.pageX - startOffset.pageX;
+      var differenceY = currentOffset.pageY - startOffset.pageY;
+
+      applyTouchMove(differenceX, differenceY);
+      startOffset = currentOffset;
+
+      var currentTime = (new Date()).getTime();
+
+      var timeGap = currentTime - startTime;
+      if (timeGap > 0) {
+        speed.x = differenceX / timeGap;
+        speed.y = differenceY / timeGap;
+        startTime = currentTime;
+      }
+
+      if (shouldPreventDefault(differenceX, differenceY)) {
+        e.stopPropagation();
+        e.preventDefault();
+      }
+    }
+  }
+  function touchEnd() {
+    if (!inGlobalTouch && inLocalTouch) {
+      inLocalTouch = false;
+
+      clearInterval(easingLoop);
+      easingLoop = setInterval(function () {
+        if (!instances.get(element)) {
+          clearInterval(easingLoop);
+          return;
+        }
+
+        if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
+          clearInterval(easingLoop);
+          return;
+        }
+
+        applyTouchMove(speed.x * 30, speed.y * 30);
+
+        speed.x *= 0.8;
+        speed.y *= 0.8;
+      }, 10);
+    }
+  }
+
+  if (supportsTouch) {
+    i.event.bind(window, 'touchstart', globalTouchStart);
+    i.event.bind(window, 'touchend', globalTouchEnd);
+    i.event.bind(element, 'touchstart', touchStart);
+    i.event.bind(element, 'touchmove', touchMove);
+    i.event.bind(element, 'touchend', touchEnd);
+  }
+
+  if (supportsIePointer) {
+    if (window.PointerEvent) {
+      i.event.bind(window, 'pointerdown', globalTouchStart);
+      i.event.bind(window, 'pointerup', globalTouchEnd);
+      i.event.bind(element, 'pointerdown', touchStart);
+      i.event.bind(element, 'pointermove', touchMove);
+      i.event.bind(element, 'pointerup', touchEnd);
+    } else if (window.MSPointerEvent) {
+      i.event.bind(window, 'MSPointerDown', globalTouchStart);
+      i.event.bind(window, 'MSPointerUp', globalTouchEnd);
+      i.event.bind(element, 'MSPointerDown', touchStart);
+      i.event.bind(element, 'MSPointerMove', touchMove);
+      i.event.bind(element, 'MSPointerUp', touchEnd);
+    }
+  }
+}
+
+module.exports = function (element, supportsTouch, supportsIePointer) {
+  var i = instances.get(element);
+  bindTouchHandler(element, i, supportsTouch, supportsIePointer);
+};
+
+},{"../instances":18,"../update-geometry":19}],17:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var cls = require('../lib/class')
+  , h = require('../lib/helper')
+  , instances = require('./instances')
+  , updateGeometry = require('./update-geometry');
+
+// Handlers
+var clickRailHandler = require('./handler/click-rail')
+  , dragScrollbarHandler = require('./handler/drag-scrollbar')
+  , keyboardHandler = require('./handler/keyboard')
+  , mouseWheelHandler = require('./handler/mouse-wheel')
+  , nativeScrollHandler = require('./handler/native-scroll')
+  , selectionHandler = require('./handler/selection')
+  , touchHandler = require('./handler/touch');
+
+module.exports = function (element, userSettings) {
+  userSettings = typeof userSettings === 'object' ? userSettings : {};
+
+  cls.add(element, 'ps-container');
+
+  // Create a plugin instance.
+  var i = instances.add(element);
+
+  i.settings = h.extend(i.settings, userSettings);
+
+  clickRailHandler(element);
+  dragScrollbarHandler(element);
+  mouseWheelHandler(element);
+  nativeScrollHandler(element);
+  selectionHandler(element);
+
+  if (h.env.supportsTouch || h.env.supportsIePointer) {
+    touchHandler(element, h.env.supportsTouch, h.env.supportsIePointer);
+  }
+  if (i.settings.useKeyboard) {
+    keyboardHandler(element);
+  }
+
+  updateGeometry(element);
+};
+
+},{"../lib/class":2,"../lib/helper":6,"./handler/click-rail":10,"./handler/drag-scrollbar":11,"./handler/keyboard":12,"./handler/mouse-wheel":13,"./handler/native-scroll":14,"./handler/selection":15,"./handler/touch":16,"./instances":18,"./update-geometry":19}],18:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var d = require('../lib/dom')
+  , defaultSettings = require('./default-setting')
+  , EventManager = require('../lib/event-manager')
+  , guid = require('../lib/guid')
+  , h = require('../lib/helper');
+
+var instances = {};
+
+function Instance(element) {
+  var i = this;
+
+  i.settings = h.clone(defaultSettings);
+  i.containerWidth = null;
+  i.containerHeight = null;
+  i.contentWidth = null;
+  i.contentHeight = null;
+
+  i.isRtl = d.css(element, 'direction') === "rtl";
+  i.isNegativeScroll = (function () {
+    var originalScrollLeft = element.scrollLeft;
+    var result = null;
+    element.scrollLeft = -1;
+    result = element.scrollLeft < 0;
+    element.scrollLeft = originalScrollLeft;
+    return result;
+  })();
+  i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
+  i.event = new EventManager();
+  i.ownerDocument = element.ownerDocument || document;
+
+  i.scrollbarXRail = d.appendTo(d.e('div', 'ps-scrollbar-x-rail'), element);
+  i.scrollbarX = d.appendTo(d.e('div', 'ps-scrollbar-x'), i.scrollbarXRail);
+  i.scrollbarXActive = null;
+  i.scrollbarXWidth = null;
+  i.scrollbarXLeft = null;
+  i.scrollbarXBottom = h.toInt(d.css(i.scrollbarXRail, 'bottom'));
+  i.isScrollbarXUsingBottom = i.scrollbarXBottom === i.scrollbarXBottom; // !isNaN
+  i.scrollbarXTop = i.isScrollbarXUsingBottom ? null : h.toInt(d.css(i.scrollbarXRail, 'top'));
+  i.railBorderXWidth = h.toInt(d.css(i.scrollbarXRail, 'borderLeftWidth')) + h.toInt(d.css(i.scrollbarXRail, 'borderRightWidth'));
+  // Set rail to display:block to calculate margins
+  d.css(i.scrollbarXRail, 'display', 'block');
+  i.railXMarginWidth = h.toInt(d.css(i.scrollbarXRail, 'marginLeft')) + h.toInt(d.css(i.scrollbarXRail, 'marginRight'));
+  d.css(i.scrollbarXRail, 'display', '');
+  i.railXWidth = null;
+  i.railXRatio = null;
+
+  i.scrollbarYRail = d.appendTo(d.e('div', 'ps-scrollbar-y-rail'), element);
+  i.scrollbarY = d.appendTo(d.e('div', 'ps-scrollbar-y'), i.scrollbarYRail);
+  i.scrollbarYActive = null;
+  i.scrollbarYHeight = null;
+  i.scrollbarYTop = null;
+  i.scrollbarYRight = h.toInt(d.css(i.scrollbarYRail, 'right'));
+  i.isScrollbarYUsingRight = i.scrollbarYRight === i.scrollbarYRight; // !isNaN
+  i.scrollbarYLeft = i.isScrollbarYUsingRight ? null : h.toInt(d.css(i.scrollbarYRail, 'left'));
+  i.scrollbarYOuterWidth = i.isRtl ? h.outerWidth(i.scrollbarY) : null;
+  i.railBorderYWidth = h.toInt(d.css(i.scrollbarYRail, 'borderTopWidth')) + h.toInt(d.css(i.scrollbarYRail, 'borderBottomWidth'));
+  d.css(i.scrollbarYRail, 'display', 'block');
+  i.railYMarginHeight = h.toInt(d.css(i.scrollbarYRail, 'marginTop')) + h.toInt(d.css(i.scrollbarYRail, 'marginBottom'));
+  d.css(i.scrollbarYRail, 'display', '');
+  i.railYHeight = null;
+  i.railYRatio = null;
+}
+
+function getId(element) {
+  if (typeof element.dataset === 'undefined') {
+    return element.getAttribute('data-ps-id');
+  } else {
+    return element.dataset.psId;
+  }
+}
+
+function setId(element, id) {
+  if (typeof element.dataset === 'undefined') {
+    element.setAttribute('data-ps-id', id);
+  } else {
+    element.dataset.psId = id;
+  }
+}
+
+function removeId(element) {
+  if (typeof element.dataset === 'undefined') {
+    element.removeAttribute('data-ps-id');
+  } else {
+    delete element.dataset.psId;
+  }
+}
+
+exports.add = function (element) {
+  var newId = guid();
+  setId(element, newId);
+  instances[newId] = new Instance(element);
+  return instances[newId];
+};
+
+exports.remove = function (element) {
+  delete instances[getId(element)];
+  removeId(element);
+};
+
+exports.get = function (element) {
+  return instances[getId(element)];
+};
+
+},{"../lib/dom":3,"../lib/event-manager":4,"../lib/guid":5,"../lib/helper":6,"./default-setting":8}],19:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var cls = require('../lib/class')
+  , d = require('../lib/dom')
+  , h = require('../lib/helper')
+  , instances = require('./instances');
+
+function getThumbSize(i, thumbSize) {
+  if (i.settings.minScrollbarLength) {
+    thumbSize = Math.max(thumbSize, i.settings.minScrollbarLength);
+  }
+  if (i.settings.maxScrollbarLength) {
+    thumbSize = Math.min(thumbSize, i.settings.maxScrollbarLength);
+  }
+  return thumbSize;
+}
+
+function updateCss(element, i) {
+  var xRailOffset = {width: i.railXWidth};
+  if (i.isRtl) {
+    xRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth - i.contentWidth;
+  } else {
+    xRailOffset.left = element.scrollLeft;
+  }
+  if (i.isScrollbarXUsingBottom) {
+    xRailOffset.bottom = i.scrollbarXBottom - element.scrollTop;
+  } else {
+    xRailOffset.top = i.scrollbarXTop + element.scrollTop;
+  }
+  d.css(i.scrollbarXRail, xRailOffset);
+
+  var yRailOffset = {top: element.scrollTop, height: i.railYHeight};
+  if (i.isScrollbarYUsingRight) {
+    if (i.isRtl) {
+      yRailOffset.right = i.contentWidth - (i.negativeScrollAdjustment + element.scrollLeft) - i.scrollbarYRight - i.scrollbarYOuterWidth;
+    } else {
+      yRailOffset.right = i.scrollbarYRight - element.scrollLeft;
+    }
+  } else {
+    if (i.isRtl) {
+      yRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth * 2 - i.contentWidth - i.scrollbarYLeft - i.scrollbarYOuterWidth;
+    } else {
+      yRailOffset.left = i.scrollbarYLeft + element.scrollLeft;
+    }
+  }
+  d.css(i.scrollbarYRail, yRailOffset);
+
+  d.css(i.scrollbarX, {left: i.scrollbarXLeft, width: i.scrollbarXWidth - i.railBorderXWidth});
+  d.css(i.scrollbarY, {top: i.scrollbarYTop, height: i.scrollbarYHeight - i.railBorderYWidth});
+}
+
+module.exports = function (element) {
+  var i = instances.get(element);
+
+  i.containerWidth = element.clientWidth;
+  i.containerHeight = element.clientHeight;
+  i.contentWidth = element.scrollWidth;
+  i.contentHeight = element.scrollHeight;
+
+  var existingRails;
+  if (!element.contains(i.scrollbarXRail)) {
+    existingRails = d.queryChildren(element, '.ps-scrollbar-x-rail');
+    if (existingRails.length > 0) {
+      existingRails.forEach(function (rail) {
+        d.remove(rail);
+      });
+    }
+    d.appendTo(i.scrollbarXRail, element);
+  }
+  if (!element.contains(i.scrollbarYRail)) {
+    existingRails = d.queryChildren(element, '.ps-scrollbar-y-rail');
+    if (existingRails.length > 0) {
+      existingRails.forEach(function (rail) {
+        d.remove(rail);
+      });
+    }
+    d.appendTo(i.scrollbarYRail, element);
+  }
+
+  if (!i.settings.suppressScrollX && i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth) {
+    i.scrollbarXActive = true;
+    i.railXWidth = i.containerWidth - i.railXMarginWidth;
+    i.railXRatio = i.containerWidth / i.railXWidth;
+    i.scrollbarXWidth = getThumbSize(i, h.toInt(i.railXWidth * i.containerWidth / i.contentWidth));
+    i.scrollbarXLeft = h.toInt((i.negativeScrollAdjustment + element.scrollLeft) * (i.railXWidth - i.scrollbarXWidth) / (i.contentWidth - i.containerWidth));
+  } else {
+    i.scrollbarXActive = false;
+    i.scrollbarXWidth = 0;
+    i.scrollbarXLeft = 0;
+    element.scrollLeft = 0;
+  }
+
+  if (!i.settings.suppressScrollY && i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight) {
+    i.scrollbarYActive = true;
+    i.railYHeight = i.containerHeight - i.railYMarginHeight;
+    i.railYRatio = i.containerHeight / i.railYHeight;
+    i.scrollbarYHeight = getThumbSize(i, h.toInt(i.railYHeight * i.containerHeight / i.contentHeight));
+    i.scrollbarYTop = h.toInt(element.scrollTop * (i.railYHeight - i.scrollbarYHeight) / (i.contentHeight - i.containerHeight));
+  } else {
+    i.scrollbarYActive = false;
+    i.scrollbarYHeight = 0;
+    i.scrollbarYTop = 0;
+    element.scrollTop = 0;
+  }
+
+  if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) {
+    i.scrollbarXLeft = i.railXWidth - i.scrollbarXWidth;
+  }
+  if (i.scrollbarYTop >= i.railYHeight - i.scrollbarYHeight) {
+    i.scrollbarYTop = i.railYHeight - i.scrollbarYHeight;
+  }
+
+  updateCss(element, i);
+
+  cls[i.scrollbarXActive ? 'add' : 'remove'](element, 'ps-active-x');
+  cls[i.scrollbarYActive ? 'add' : 'remove'](element, 'ps-active-y');
+};
+
+},{"../lib/class":2,"../lib/dom":3,"../lib/helper":6,"./instances":18}],20:[function(require,module,exports){
+/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+ * Licensed under the MIT License
+ */
+'use strict';
+
+var d = require('../lib/dom')
+  , h = require('../lib/helper')
+  , instances = require('./instances')
+  , updateGeometry = require('./update-geometry');
+
+module.exports = function (element) {
+  var i = instances.get(element);
+
+  if (!i) {
+    return;
+  }
+
+  // Recalcuate negative scrollLeft adjustment
+  i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
+
+  // Recalculate rail margins
+  d.css(i.scrollbarXRail, 'display', 'block');
+  d.css(i.scrollbarYRail, 'display', 'block');
+  i.railXMarginWidth = h.toInt(d.css(i.scrollbarXRail, 'marginLeft')) + h.toInt(d.css(i.scrollbarXRail, 'marginRight'));
+  i.railYMarginHeight = h.toInt(d.css(i.scrollbarYRail, 'marginTop')) + h.toInt(d.css(i.scrollbarYRail, 'marginBottom'));
+
+  // Hide scrollbars not to affect scrollWidth and scrollHeight
+  d.css(i.scrollbarXRail, 'display', 'none');
+  d.css(i.scrollbarYRail, 'display', 'none');
+
+  updateGeometry(element);
+
+  d.css(i.scrollbarXRail, 'display', '');
+  d.css(i.scrollbarYRail, 'display', '');
+};
+
+},{"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-geometry":19}]},{},[1]);

文件差异内容过多而无法显示
+ 1 - 0
jet/static/jet/vendor/perfect-scrollbar/js/perfect-scrollbar.min.js


+ 34 - 20
jet/templates/admin/base.html

@@ -10,6 +10,7 @@
     <link href="{% static "jet/vendor/select2/css/select2.min.css" %}" rel="stylesheet" />
     <link href="{% static "jet/vendor/jquery-ui/jquery-ui.min.css" %}" rel="stylesheet" />
     <link href="{% static "jet/vendor/jquery-ui-timepicker/jquery.ui.timepicker.css" %}" rel="stylesheet" />
+    <link href="{% static "jet/vendor/perfect-scrollbar/css/perfect-scrollbar.css" %}" rel="stylesheet" />
     <link href="{% static "jet/css/icons/style.css" %}" rel="stylesheet" />
     <link href="{% static "jet/css/themes/"|add:THEME|add:"/base.css" %}" rel="stylesheet" />
     <link href="{% static "jet/css/themes/"|add:THEME|add:"/select2.theme.css" %}" rel="stylesheet" />
@@ -30,6 +31,8 @@
     <script src="{% static "jet/vendor/jquery-ui/jquery-ui.min.js" %}"></script>
     <script src="{% static "jet/vendor/jquery-ui-timepicker/jquery.ui.timepicker.js" %}"></script>
     <script src="{% static "jet/vendor/select2/js/select2.full.min.js" %}"></script>
+    <script src="{% static "jet/vendor/perfect-scrollbar/js/perfect-scrollbar.min.js" %}"></script>
+    <script src="{% static "jet/vendor/perfect-scrollbar/js/perfect-scrollbar.jquery.min.js" %}"></script>
     {% if LANGUAGE_CODE|slice:":2" != 'en' %}
         {% with "jet/vendor/jquery-ui/i18n/datepicker-"|add:LANGUAGE_CODE|add:".js" as url %}
             <script src="{% static url %}"></script>
@@ -110,9 +113,9 @@
                     {% endif %}
                 {% endblock messages %}
 
-            <div class="content-sidebar">
-                        {% block sidebar %}{% endblock %}
-                    </div>
+                <div class="content-sidebar">
+                    {% block sidebar %}{% endblock %}
+                </div>
 
                 <div id="content" class="cf {% block coltype %}colM{% endblock %}">
                     {% block pretitle %}{% endblock %}
@@ -136,16 +139,34 @@
                         {% block branding %}{% endblock %}
                     </div>
                     <ul class="sidebar-menu">
-                        {% if user.is_active and user.is_staff %}
-                            <li class="sidebar-menu-item">
-                                <span class="sidebar-menu-item-icon icon-data"></span> <a href="{% url 'admin:index' %}" class="sidebar-menu-item-link">{% trans 'Home' %}</a>
-                            </li>
-                        {% endif %}
-                        {% if site_url %}
-                            <li class="sidebar-menu-item">
-                                <span class="sidebar-menu-item-icon icon-open-external"></span> <a href="{{ site_url }}" class="sidebar-menu-item-link">{% trans 'View site' %}</a>
-                            </li>
-                        {% endif %}
+                        <li class="sidebar-menu-item no-horizontal-padding">
+                            <ul class="sidebar-menu-item-list compact">
+                                {% if user.is_active and user.is_staff %}
+                                    <li class="sidebar-menu-item-list-item">
+                                        <a href="{% url 'admin:index' %}" class="sidebar-menu-item-list-item-link">
+                                            <span class="sidebar-menu-item-list-item-icon icon-data"></span> {% trans 'Home' %}
+                                        </a>
+                                    </li>
+                                {% endif %}
+                                {% if site_url %}
+                                    <li class="sidebar-menu-item-list-item">
+                                        <a href="{{ site_url }}" class="sidebar-menu-item-list-item-link">
+                                            <span class="sidebar-menu-item-list-item-icon icon-open-external"></span> {% trans 'View site' %}
+                                        </a>
+                                    </li>
+                                {% endif %}
+                                {% url 'django-admindocs-docroot' as docsroot %}
+                                {% if docsroot %}
+                                    <li class="sidebar-menu-item-list-item">
+                                        <a href="{{ docsroot }}" class="sidebar-menu-item-list-item-link">
+                                            <span class="sidebar-menu-item-list-item-icon icon-book"></span> {% trans 'Documentation' %}
+                                        </a>
+                                    </li>
+                                {% endif %}
+                                {% block nav-global %}{% endblock %}
+                            </ul>
+                        </li>
+
                         {% if user.is_active and user.is_staff %}
                             {% get_menu as app_list %}
                             {% if app_list.apps or app_list.pinned_apps %}
@@ -220,13 +241,6 @@
                                     </li>
                                 </ul>
                             </li>
-                            {% url 'django-admindocs-docroot' as docsroot %}
-                            {% if docsroot %}
-                                <li class="sidebar-menu-item">
-                                    <span class="sidebar-menu-item-icon icon-book"></span> <a href="{{ docsroot }}" class="sidebar-menu-item-link">{% trans 'Documentation' %}</a>
-                                </li>
-                            {% endif %}
-                            {% block nav-global %}{% endblock %}
                         {% endif %}
                     </ul>
                 </div>

+ 2 - 2
jet/templates/admin/search_form.html

@@ -13,13 +13,13 @@
             {% endif %}
         {% endblock %}
 
-        <span class="changelist-filter-submit-block">
+        <div class="changelist-filter-submit-block">
             <input type="submit" value="{% trans 'Search' %}" />
 
             {% if show_result_count %}
                 <span class="small quiet">{% blocktrans count counter=cl.result_count %}{{ counter }} result{% plural %}{{ counter }} results{% endblocktrans %} (<a href="?{% if cl.is_popup %}_popup=1{% endif %}">{% if cl.show_full_result_count %}{% blocktrans with full_result_count=cl.full_result_count %}{{ full_result_count }} total{% endblocktrans %}{% else %}{% trans "Show all" %}{% endif %}</a>)</span>
             {% endif %}
-        </span>
+        </div>
 
         {% for pair in cl.params.items %}
             {% ifnotequal pair.0 search_var %}<input type="hidden" name="{{ pair.0 }}" value="{{ pair.1 }}"/>{% endifnotequal %}

+ 16 - 0
jet/tests/test_views.py

@@ -165,6 +165,22 @@ class ViewsTestCase(TestCase):
         module = UserDashboardModule.objects.get(pk=response['id'])
         self.assertNotEqual(module, None)
 
+    def test_add_user_app_dashboard_module_view(self):
+        app_label = 'auth'
+        response = self.admin.post(reverse('jet-dashboard:add_user_dashboard_module'), {
+            'app_label': app_label,
+            'type': 'available_children',
+            'module': 0
+        })
+
+        self.assertEqual(response.status_code, 200)
+        response = json.loads(response.content.decode())
+        self.assertFalse(response['error'])
+        self.assertNotEqual(response['id'], None)
+        module = UserDashboardModule.objects.get(pk=response['id'])
+        self.assertNotEqual(module, None)
+        self.assertEqual(module.app_label, app_label)
+
     def test_update_dashboard_module_collapse_view(self):
         module = UserDashboardModule.objects.create(
             title='',

部分文件因为文件数量过多而无法显示