Modified classmethod queries that determine if a Model is sortable to only retieve one record and not use count.

Fixed jQueryUI highlight method call in success handler of ajax function when dragging stops.
Fixed missing script resource for jquery.effects.core.js
master
Brandon Taylor 2011-11-16 00:48:14 -06:00 committed by Brandon Taylor
parent 638f26df27
commit 8365043e0e
77 changed files with 10917 additions and 10892 deletions

13
.gitignore vendored 100644 → 100755
View File

@ -1,6 +1,7 @@
.project .project
dist dist
django_admin_sortable.egg-info django_admin_sortable.egg-info
.pydevproject .pydevproject
*.pyc *.pyc
*.pyo *.pyo
.idea

4
AUTHORS 100644 → 100755
View File

@ -1,2 +1,2 @@
This software is maintained by: This software is maintained by:
Brandon Taylor <btaylorweb@gmail.com> Brandon Taylor <btaylorweb@gmail.com>

20
COPYRIGHT 100644 → 100755
View File

@ -1,11 +1,11 @@
(c) Copyright 2011 Brandon Taylor - bTaylorWeb (c) Copyright 2011 Brandon Taylor - bTaylorWeb
django-admin-sortable is free software: you can django-admin-sortable is free software: you can
redistribute it and/or modify it under redistribute it and/or modify it under
the terms of the Apache Public License v2. the terms of the Apache Public License v2.
django-admin-sortable is distributed in the hope django-admin-sortable is distributed in the hope
that it will be useful, but WITHOUT ANY that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. FOR A PARTICULAR PURPOSE.

6
MANIFEST.in 100644 → 100755
View File

@ -1,4 +1,4 @@
recursive-include adminsortable/static * recursive-include adminsortable/static *
recursive-include adminsortable/templates * recursive-include adminsortable/templates *
recursive-include adminsortable/locale * recursive-include adminsortable/locale *
prune sample_project prune sample_project

326
README 100644 → 100755
View File

@ -1,163 +1,163 @@
============= =============
admin-sortable admin-sortable
============= =============
What is it? What is it?
============= =============
The adminsortable app adds generic drag-and-drop facilities The adminsortable app adds generic drag-and-drop facilities
to any Django model class or Tabular Inline via Django Admin to any Django model class or Tabular Inline via Django Admin
and jQueryUI. and jQueryUI.
Installation Installation
============= =============
1. Run ``setup.py`` or add ``adminsortable`` to your PYTHONPATH. 1. Run ``setup.py`` or add ``adminsortable`` to your PYTHONPATH.
2. Copy the ``adminsortable`` folder from the static folder to the 2. Copy the ``adminsortable`` folder from the static folder to the
location you server static files from, or if you're using the StaticFiles app location you server static files from, or if you're using the StaticFiles app
https://docs.djangoproject.com/en/1.3/ref/contrib/staticfiles/, https://docs.djangoproject.com/en/1.3/ref/contrib/staticfiles/,
run: $ python manage.py collectstatic to move the files to the location run: $ python manage.py collectstatic to move the files to the location
you've specified for static files. you've specified for static files.
3. Add ``adminsortable`` to your INSTALLED_APPS. 3. Add ``adminsortable`` to your INSTALLED_APPS.
4. Have a look at the included sample_project to see working examples. 4. Have a look at the included sample_project to see working examples.
The login credentials for admin are: admin/admin The login credentials for admin are: admin/admin
When a model is sortable, a tool-area link will be added that says "Change Order". When a model is sortable, a tool-area link will be added that says "Change Order".
Click this link, and you will be taken to the custom view where you can drag-and-drop Click this link, and you will be taken to the custom view where you can drag-and-drop
the records into order. the records into order.
Tabular inlines may be drag-and-dropped into any order directly from the change form. Tabular inlines may be drag-and-dropped into any order directly from the change form.
Usage Usage
============= =============
Models Models
---------------------- ----------------------
To add sorting to a model, your model needs to inherit from ``Sortable`` and To add sorting to a model, your model needs to inherit from ``Sortable`` and
have an inner Meta class that inherits from ``Sortable.Meta`` have an inner Meta class that inherits from ``Sortable.Meta``
#models.py #models.py
from adminsortable.models import Sortable from adminsortable.models import Sortable
class MySortableClass(Sortable): class MySortableClass(Sortable):
class Meta(Sortable.Meta) class Meta(Sortable.Meta)
title = models.CharField(max_length=50) title = models.CharField(max_length=50)
def __unicode__(self): def __unicode__(self):
return self.title return self.title
For models that you want sortable relative to a ``ForeignKey`` field, you need to For models that you want sortable relative to a ``ForeignKey`` field, you need to
specify an ``@classmethod`` that returns a double: the foreign key class, and the specify an ``@classmethod`` that returns a double: the foreign key class, and the
name of the foreign key property as defined on your model, as a string. name of the foreign key property as defined on your model, as a string.
#admin.py #admin.py
class Category(models.Model): class Category(models.Model):
title = models.CharField(max_length=50) title = models.CharField(max_length=50)
... ...
class MySortableClass(Sortable): class MySortableClass(Sortable):
class Meta(Sortable.Meta) class Meta(Sortable.Meta)
category = models.ForeignKey(Category) category = models.ForeignKey(Category)
title = models.CharField(max_length=50) title = models.CharField(max_length=50)
def __unicode__(self): def __unicode__(self):
return self.title return self.title
@classmethod @classmethod
def sortable_by(cls): def sortable_by(cls):
return Category, 'category' return Category, 'category'
Sortable has one field: `order` and adds a default ordering value set to `order`. Sortable has one field: `order` and adds a default ordering value set to `order`.
South South
------ ------
If you're adding Sorting to an existing model, it is recommended that you use django-south, If you're adding Sorting to an existing model, it is recommended that you use django-south,
http://south.areacode.com/ to create a migration to add the "order" field to your model. http://south.areacode.com/ to create a migration to add the "order" field to your model.
*Django Admin Usage* *Django Admin Usage*
To enable sorting in the admin, you need to inherit from SortableAdmin: To enable sorting in the admin, you need to inherit from SortableAdmin:
from django.contrib import admin from django.contrib import admin
from myapp.models import MySortableClass from myapp.models import MySortableClass
from adminsortable.admin import SortableAdmin from adminsortable.admin import SortableAdmin
class MySortableAdminClass(SortableAdmin): class MySortableAdminClass(SortableAdmin):
"""Any admin options you need go here""" """Any admin options you need go here"""
admin.site.register(MySortableClass, MySortableAdminClass) admin.site.register(MySortableClass, MySortableAdminClass)
To enable sorting on TabularInline models, you need to inherit from To enable sorting on TabularInline models, you need to inherit from
SortableTabularInline: SortableTabularInline:
from adminsortable.admin import SortableTabularInline from adminsortable.admin import SortableTabularInline
class MySortableTabularInline(SortableTabularInline): class MySortableTabularInline(SortableTabularInline):
"""Your inline options go here""" """Your inline options go here"""
To enable sorting on StackedInline models, you need to inherit from To enable sorting on StackedInline models, you need to inherit from
SortableStackedInline: SortableStackedInline:
from adminsortable.admin import SortableStackedInline from adminsortable.admin import SortableStackedInline
class MySortableStackedInline(SortableStackedInline): class MySortableStackedInline(SortableStackedInline):
"""Your inline options go here""" """Your inline options go here"""
!!! *IMPORTANT* !!! !!! *IMPORTANT* !!!
With stacked inline models, their height can dynamically increase, With stacked inline models, their height can dynamically increase,
which can cause sortable stacked inlines to not behave as expected. which can cause sortable stacked inlines to not behave as expected.
If the height of the stacked inline is going to be very tall, I would If the height of the stacked inline is going to be very tall, I would
suggest NOT using SortableStackedInline. I'm currently working on suggest NOT using SortableStackedInline. I'm currently working on
a way to make this more usable. a way to make this more usable.
Rationale Rationale
============= =============
Other projects have added drag-and-drop ordering to the ChangeList Other projects have added drag-and-drop ordering to the ChangeList
view, however this introduces a couple of problems... view, however this introduces a couple of problems...
- The ChangeList view supports pagination, which makes drag-and-drop - The ChangeList view supports pagination, which makes drag-and-drop
ordering across pages impossible. ordering across pages impossible.
- The ChangeList view by default, does not order records based on a - The ChangeList view by default, does not order records based on a
foreign key, nor distinguish between rows that are associated with a foreign key, nor distinguish between rows that are associated with a
foreign key. This makes ordering the records grouped by a foreign key foreign key. This makes ordering the records grouped by a foreign key
impossible. impossible.
- The ChangeList supports in-line editing, and adding drag-and-drop - The ChangeList supports in-line editing, and adding drag-and-drop
ordering on top of that just seemed a little much in my opinion. ordering on top of that just seemed a little much in my opinion.
Status Status
============= =============
admin-sortable is currently used in production. admin-sortable is currently used in production.
Feautures Feautures
============= =============
Current Current
--------- ---------
- Supports Django 1.3+ - Supports Django 1.3+
- Adds an admin view to any model that inherits from Sortable and SortableAdmin - Adds an admin view to any model that inherits from Sortable and SortableAdmin
that allows you to drag and drop objects into any order via jQueryUI. that allows you to drag and drop objects into any order via jQueryUI.
- Adds drag and drop ordering to Tabular and Stacked Inline models that inherit from - Adds drag and drop ordering to Tabular and Stacked Inline models that inherit from
SortableTabularInline and SortableStackedInline SortableTabularInline and SortableStackedInline
- Allows ordering of objects that are sorted on a Foreign Key, and adds ordering - Allows ordering of objects that are sorted on a Foreign Key, and adds ordering
to the foreign key object if it also inherits from Sortable. to the foreign key object if it also inherits from Sortable.
- Supports non-integer primary keys. - Supports non-integer primary keys.
Future Future
------ ------
- Support for foreign keys that are self referential - Support for foreign keys that are self referential
- Support for ForeignKeys that have not been previously defined - Support for ForeignKeys that have not been previously defined
- More unit tests - More unit tests
Requirements Requirements
============= =============
Sample Project Sample Project
---------------- ----------------
Requires django-appmedia, included Requires django-appmedia, included
License License
============= =============
The admin-sortable app is released The admin-sortable app is released
under the Apache Public License v2. under the Apache Public License v2.

0
adminsortable/__init__.py 100644 → 100755
View File

0
adminsortable/admin.py 100644 → 100755
View File

View File

@ -1,36 +1,36 @@
#, fuzzy #, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: adminsortable\n" "Project-Id-Version: adminsortable\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-09-22 15:42+0200\n" "POT-Creation-Date: 2011-09-22 15:42+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: templates/adminsortable/change_list.html:32 #: templates/adminsortable/change_list.html:32
#, python-format #, python-format
msgid "Drag and drop %(sort_type)s %(model)s to change their order." msgid "Drag and drop %(sort_type)s %(model)s to change their order."
msgstr "" msgstr ""
#: templates/adminsortable/change_list.html:34 #: templates/adminsortable/change_list.html:34
#, python-format #, python-format
msgid "Drag and drop %(model)s to change their order." msgid "Drag and drop %(model)s to change their order."
msgstr "" msgstr ""
#: templates/adminsortable/change_list.html:39 #: templates/adminsortable/change_list.html:39
#, python-format #, python-format
msgid "" msgid ""
"You may also drag and drop %(sortable_by_class_display_name)s to change " "You may also drag and drop %(sortable_by_class_display_name)s to change "
"thier order." "thier order."
msgstr "" msgstr ""
#: templates/adminsortable/change_list.html:50 #: templates/adminsortable/change_list.html:50
#, python-format #, python-format
msgid "Return to %(model)s" msgid "Return to %(model)s"
msgstr "" msgstr ""
#: templates/adminsortable/change_list_with_sort_link.html:6 #: templates/adminsortable/change_list_with_sort_link.html:6
msgid "Change Order" msgid "Change Order"
msgstr "" msgstr ""

View File

View File

@ -1,39 +1,39 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: adminsortable\n" "Project-Id-Version: adminsortable\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-09-22 15:42+0200\n" "POT-Creation-Date: 2011-09-22 15:42+0200\n"
"PO-Revision-Date: 2011-09-22 15:50+0100\n" "PO-Revision-Date: 2011-09-22 15:50+0100\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Jaap Roes <jaap@eight.nl>\n" "Last-Translator: Jaap Roes <jaap@eight.nl>\n"
"Language-Team: \n" "Language-Team: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-Language: Dutch\n" "X-Poedit-Language: Dutch\n"
"X-Poedit-Country: NETHERLANDS\n" "X-Poedit-Country: NETHERLANDS\n"
#: templates/adminsortable/change_list.html:32 #: templates/adminsortable/change_list.html:32
#, python-format #, python-format
msgid "Drag and drop %(sort_type)s %(model)s to change their order." msgid "Drag and drop %(sort_type)s %(model)s to change their order."
msgstr "Sleep %(sort_type)s %(model)s om de volgorde te veranderen" msgstr "Sleep %(sort_type)s %(model)s om de volgorde te veranderen"
#: templates/adminsortable/change_list.html:34 #: templates/adminsortable/change_list.html:34
#, python-format #, python-format
msgid "Drag and drop %(model)s to change their order." msgid "Drag and drop %(model)s to change their order."
msgstr "Sleep %(model)s om de volgorde te veranderen" msgstr "Sleep %(model)s om de volgorde te veranderen"
#: templates/adminsortable/change_list.html:39 #: templates/adminsortable/change_list.html:39
#, python-format #, python-format
msgid "You may also drag and drop %(sortable_by_class_display_name)s to change thier order." msgid "You may also drag and drop %(sortable_by_class_display_name)s to change thier order."
msgstr "U kunt ook %(sortable_by_class_display_name)s slepen om de volgorde te veranderen." msgstr "U kunt ook %(sortable_by_class_display_name)s slepen om de volgorde te veranderen."
#: templates/adminsortable/change_list.html:50 #: templates/adminsortable/change_list.html:50
#, python-format #, python-format
msgid "Return to %(model)s" msgid "Return to %(model)s"
msgstr "Terug naar %(model)s" msgstr "Terug naar %(model)s"
#: templates/adminsortable/change_list_with_sort_link.html:6 #: templates/adminsortable/change_list_with_sort_link.html:6
msgid "Change Order" msgid "Change Order"
msgstr "Volgorde veranderen" msgstr "Volgorde veranderen"

26
adminsortable/models.py 100644 → 100755
View File

@ -3,15 +3,30 @@ from django.db import models
class Sortable(models.Model): class Sortable(models.Model):
"""
Unfortunately, Django doesn't support using more than one AutoField in a model
or this class could be simplified.
`is_sortable` determines whether or not the Model is sortable by determining
if the last value of `order` is greater than the default of 1, which should be
present if there is only one object.
`model_type_id` returns the ContentType.id for the Model that inherits Sortable
`save` the override of save increments the last/highest value of order by 1
"""
order = models.PositiveIntegerField(editable=False, default=1, db_index=True) order = models.PositiveIntegerField(editable=False, default=1, db_index=True)
class Meta: class Meta:
abstract = True abstract = True
ordering = ['order', 'id'] ordering = ['order']
@classmethod @classmethod
def is_sortable(cls): def is_sortable(cls):
return True if cls.objects.count() > 1 else False try:
return True if cls.objects.order_by('-order')[:1][0].order > 1 else False
except IndexError:
return False
@classmethod @classmethod
def model_type_id(cls): def model_type_id(cls):
@ -19,5 +34,10 @@ class Sortable(models.Model):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if not self.id: if not self.id:
self.order = self.__class__.objects.count() + 1 try:
#increment the order field by adding one to the last value of order
self.order = self.__class__.objects.order_by('-order')[:1][0].order + 1
except IndexError:
#order defaults to 1
pass
super(Sortable, self).save(*args, **kwargs) super(Sortable, self).save(*args, **kwargs)

View File

@ -1,48 +1,48 @@
#sortable ul #sortable ul
{ {
-webkit-padding-start: 0; -webkit-padding-start: 0;
padding-left: 0; padding-left: 0;
margin-top: 0.75em; margin-top: 0.75em;
} }
#sortable ul ul #sortable ul ul
{ {
margin-left: 1em; margin-left: 1em;
} }
#sortable ul li, #sortable ul li,
#sortable ul li a #sortable ul li a
{ {
cursor: move; cursor: move;
} }
#sortable ul li #sortable ul li
{ {
overflow: auto; overflow: auto;
margin-left: 0; margin-left: 0;
display: block; display: block;
} }
#sortable .sortable #sortable .sortable
{ {
list-style: none; list-style: none;
font-weight: 800; font-weight: 800;
margin-bottom: 0.75em; margin-bottom: 0.75em;
} }
#sortable .sortable.single, #sortable .sortable.single,
#sortable ul ul a #sortable ul ul a
{ {
font-weight: 400; font-weight: 400;
} }
#sortable ul ul a #sortable ul ul a
{ {
color: #5B80B2; color: #5B80B2;
margin-bottom: 0; margin-bottom: 0;
} }
.sortable a:hover .sortable a:hover
{ {
color: #003366; color: #003366;
} }

View File

@ -1,21 +1,21 @@
jQuery(function($){ jQuery(function($){
$('.sortable').sortable({ $('.sortable').sortable({
axis : 'y', axis : 'y',
containment : 'parent', containment : 'parent',
tolerance : 'pointer', tolerance : 'pointer',
items : 'li', items : 'li',
stop : function(event, ui) stop : function(event, ui)
{ {
var indexes = Array(); var indexes = Array();
ui.item.parent().children('li').each(function(i) ui.item.parent().children('li').each(function(i)
{ {
indexes.push($(this).find(':hidden[name="pk"]').val()); indexes.push($(this).find(':hidden[name="pk"]').val());
}); });
$.ajax({ $.ajax({
url: ui.item.find('a.admin_sorting_url').attr('href'), url: ui.item.find('a.admin_sorting_url').attr('href'),
type: 'POST', type: 'POST',
data: { indexes: indexes.join(',') } data: { indexes: indexes.join(',') }
}); });
} }
}); });
}); });

View File

@ -1,31 +1,31 @@
jQuery(function($){ jQuery(function($){
if ($(':hidden[name="admin_sorting_url"]').length > 0) if ($(':hidden[name="admin_sorting_url"]').length > 0)
{ {
$('.inline-group').sortable({ $('.inline-group').sortable({
axis : 'y', axis : 'y',
containment : 'parent', containment : 'parent',
tolerance : 'pointer', tolerance : 'pointer',
items : '.inline-related', items : '.inline-related',
stop : function(event, ui) stop : function(event, ui)
{ {
var indexes = Array(); var indexes = Array();
ui.item.parent().children('.inline-related').each(function(i) ui.item.parent().children('.inline-related').each(function(i)
{ {
index_value = $(this).find(':hidden[name$="-id"]').val(); index_value = $(this).find(':hidden[name$="-id"]').val();
if (index_value != "" && index_value != undefined) if (index_value != "" && index_value != undefined)
indexes.push(index_value); indexes.push(index_value);
}); });
$.ajax({ $.ajax({
url: ui.item.parent().find(':hidden[name="admin_sorting_url"]').val(), url: ui.item.parent().find(':hidden[name="admin_sorting_url"]').val(),
type: 'POST', type: 'POST',
data: { indexes : indexes.join(',') }, data: { indexes : indexes.join(',') },
success: function() success: function()
{ {
ui.effect('highlight'); ui.item.effect('highlight', {}, 1000);
} }
}); });
} }
}); });
} }
}); });

View File

@ -1,37 +1,37 @@
jQuery(function($){ jQuery(function($){
if ($(':hidden[name="admin_sorting_url"]').length > 0) if ($(':hidden[name="admin_sorting_url"]').length > 0)
{ {
var tabular_inline_rows = $('.tabular table tbody tr'); var tabular_inline_rows = $('.tabular table tbody tr');
tabular_inline_rows.addClass('sortable'); tabular_inline_rows.addClass('sortable');
$('.tabular.inline-related').sortable({ $('.tabular.inline-related').sortable({
axis : 'y', axis : 'y',
containment : 'parent', containment : 'parent',
tolerance : 'pointer', tolerance : 'pointer',
items : 'tr', items : 'tr',
stop : function(event, ui) stop : function(event, ui)
{ {
var indexes = Array(); var indexes = Array();
ui.item.parent().children('tr').each(function(i) ui.item.parent().children('tr').each(function(i)
{ {
index_value = $(this).find('.original :hidden:first').val(); index_value = $(this).find('.original :hidden:first').val();
if (index_value != "" && index_value != undefined) if (index_value != "" && index_value != undefined)
indexes.push(index_value); indexes.push(index_value);
}); });
$.ajax({ $.ajax({
url: ui.item.parent().find(':hidden[name="admin_sorting_url"]').val(), url: ui.item.parent().find(':hidden[name="admin_sorting_url"]').val(),
type: 'POST', type: 'POST',
data: { indexes : indexes.join(',') }, data: { indexes : indexes.join(',') },
success: function() success: function()
{ {
//highlight sorted row, then re-stripe table //highlight sorted row, then re-stripe table
ui.item.effect('highlight', {}, 1000); ui.item.effect('highlight', {}, 1000);
tabular_inline_rows.removeClass('row1 row2'); tabular_inline_rows.removeClass('row1 row2');
$('.tabular table tbody tr:odd').addClass('row2'); $('.tabular table tbody tr:odd').addClass('row2');
$('.tabular table tbody tr:even').addClass('row1'); $('.tabular table tbody tr:even').addClass('row1');
} }
}); });
} }
}); });
} }
}); });

File diff suppressed because it is too large Load Diff

View File

@ -1,50 +1,50 @@
/* /*
* jQuery UI Effects Highlight 1.8.16 * jQuery UI Effects Highlight 1.8.16
* *
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses. * Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license * http://jquery.org/license
* *
* http://docs.jquery.com/UI/Effects/Highlight * http://docs.jquery.com/UI/Effects/Highlight
* *
* Depends: * Depends:
* jquery.effects.core.js * jquery.effects.core.js
*/ */
(function( $, undefined ) { (function( $, undefined ) {
$.effects.highlight = function(o) { $.effects.highlight = function(o) {
return this.queue(function() { return this.queue(function() {
var elem = $(this), var elem = $(this),
props = ['backgroundImage', 'backgroundColor', 'opacity'], props = ['backgroundImage', 'backgroundColor', 'opacity'],
mode = $.effects.setMode(elem, o.options.mode || 'show'), mode = $.effects.setMode(elem, o.options.mode || 'show'),
animation = { animation = {
backgroundColor: elem.css('backgroundColor') backgroundColor: elem.css('backgroundColor')
}; };
if (mode == 'hide') { if (mode == 'hide') {
animation.opacity = 0; animation.opacity = 0;
} }
$.effects.save(elem, props); $.effects.save(elem, props);
elem elem
.show() .show()
.css({ .css({
backgroundImage: 'none', backgroundImage: 'none',
backgroundColor: o.options.color || '#ffff99' backgroundColor: o.options.color || '#ffff99'
}) })
.animate(animation, { .animate(animation, {
queue: false, queue: false,
duration: o.duration, duration: o.duration,
easing: o.options.easing, easing: o.options.easing,
complete: function() { complete: function() {
(mode == 'hide' && elem.hide()); (mode == 'hide' && elem.hide());
$.effects.restore(elem, props); $.effects.restore(elem, props);
(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter')); (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
(o.callback && o.callback.apply(this, arguments)); (o.callback && o.callback.apply(this, arguments));
elem.dequeue(); elem.dequeue();
} }
}); });
}); });
}; };
})(jQuery); })(jQuery);

View File

@ -1,314 +1,314 @@
/*! /*!
* jQuery UI 1.8.16 * jQuery UI 1.8.16
* *
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses. * Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license * http://jquery.org/license
* *
* http://docs.jquery.com/UI * http://docs.jquery.com/UI
*/ */
(function( $, undefined ) { (function( $, undefined ) {
// prevent duplicate loading // prevent duplicate loading
// this is only a problem because we proxy existing functions // this is only a problem because we proxy existing functions
// and we don't want to double proxy them // and we don't want to double proxy them
$.ui = $.ui || {}; $.ui = $.ui || {};
if ( $.ui.version ) { if ( $.ui.version ) {
return; return;
} }
$.extend( $.ui, { $.extend( $.ui, {
version: "1.8.16", version: "1.8.16",
keyCode: { keyCode: {
ALT: 18, ALT: 18,
BACKSPACE: 8, BACKSPACE: 8,
CAPS_LOCK: 20, CAPS_LOCK: 20,
COMMA: 188, COMMA: 188,
COMMAND: 91, COMMAND: 91,
COMMAND_LEFT: 91, // COMMAND COMMAND_LEFT: 91, // COMMAND
COMMAND_RIGHT: 93, COMMAND_RIGHT: 93,
CONTROL: 17, CONTROL: 17,
DELETE: 46, DELETE: 46,
DOWN: 40, DOWN: 40,
END: 35, END: 35,
ENTER: 13, ENTER: 13,
ESCAPE: 27, ESCAPE: 27,
HOME: 36, HOME: 36,
INSERT: 45, INSERT: 45,
LEFT: 37, LEFT: 37,
MENU: 93, // COMMAND_RIGHT MENU: 93, // COMMAND_RIGHT
NUMPAD_ADD: 107, NUMPAD_ADD: 107,
NUMPAD_DECIMAL: 110, NUMPAD_DECIMAL: 110,
NUMPAD_DIVIDE: 111, NUMPAD_DIVIDE: 111,
NUMPAD_ENTER: 108, NUMPAD_ENTER: 108,
NUMPAD_MULTIPLY: 106, NUMPAD_MULTIPLY: 106,
NUMPAD_SUBTRACT: 109, NUMPAD_SUBTRACT: 109,
PAGE_DOWN: 34, PAGE_DOWN: 34,
PAGE_UP: 33, PAGE_UP: 33,
PERIOD: 190, PERIOD: 190,
RIGHT: 39, RIGHT: 39,
SHIFT: 16, SHIFT: 16,
SPACE: 32, SPACE: 32,
TAB: 9, TAB: 9,
UP: 38, UP: 38,
WINDOWS: 91 // COMMAND WINDOWS: 91 // COMMAND
} }
}); });
// plugins // plugins
$.fn.extend({ $.fn.extend({
propAttr: $.fn.prop || $.fn.attr, propAttr: $.fn.prop || $.fn.attr,
_focus: $.fn.focus, _focus: $.fn.focus,
focus: function( delay, fn ) { focus: function( delay, fn ) {
return typeof delay === "number" ? return typeof delay === "number" ?
this.each(function() { this.each(function() {
var elem = this; var elem = this;
setTimeout(function() { setTimeout(function() {
$( elem ).focus(); $( elem ).focus();
if ( fn ) { if ( fn ) {
fn.call( elem ); fn.call( elem );
} }
}, delay ); }, delay );
}) : }) :
this._focus.apply( this, arguments ); this._focus.apply( this, arguments );
}, },
scrollParent: function() { scrollParent: function() {
var scrollParent; var scrollParent;
if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
scrollParent = this.parents().filter(function() { scrollParent = this.parents().filter(function() {
return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
}).eq(0); }).eq(0);
} else { } else {
scrollParent = this.parents().filter(function() { scrollParent = this.parents().filter(function() {
return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
}).eq(0); }).eq(0);
} }
return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent; return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
}, },
zIndex: function( zIndex ) { zIndex: function( zIndex ) {
if ( zIndex !== undefined ) { if ( zIndex !== undefined ) {
return this.css( "zIndex", zIndex ); return this.css( "zIndex", zIndex );
} }
if ( this.length ) { if ( this.length ) {
var elem = $( this[ 0 ] ), position, value; var elem = $( this[ 0 ] ), position, value;
while ( elem.length && elem[ 0 ] !== document ) { while ( elem.length && elem[ 0 ] !== document ) {
// Ignore z-index if position is set to a value where z-index is ignored by the browser // Ignore z-index if position is set to a value where z-index is ignored by the browser
// This makes behavior of this function consistent across browsers // This makes behavior of this function consistent across browsers
// WebKit always returns auto if the element is positioned // WebKit always returns auto if the element is positioned
position = elem.css( "position" ); position = elem.css( "position" );
if ( position === "absolute" || position === "relative" || position === "fixed" ) { if ( position === "absolute" || position === "relative" || position === "fixed" ) {
// IE returns 0 when zIndex is not specified // IE returns 0 when zIndex is not specified
// other browsers return a string // other browsers return a string
// we ignore the case of nested elements with an explicit value of 0 // we ignore the case of nested elements with an explicit value of 0
// <div style="z-index: -10;"><div style="z-index: 0;"></div></div> // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
value = parseInt( elem.css( "zIndex" ), 10 ); value = parseInt( elem.css( "zIndex" ), 10 );
if ( !isNaN( value ) && value !== 0 ) { if ( !isNaN( value ) && value !== 0 ) {
return value; return value;
} }
} }
elem = elem.parent(); elem = elem.parent();
} }
} }
return 0; return 0;
}, },
disableSelection: function() { disableSelection: function() {
return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
".ui-disableSelection", function( event ) { ".ui-disableSelection", function( event ) {
event.preventDefault(); event.preventDefault();
}); });
}, },
enableSelection: function() { enableSelection: function() {
return this.unbind( ".ui-disableSelection" ); return this.unbind( ".ui-disableSelection" );
} }
}); });
$.each( [ "Width", "Height" ], function( i, name ) { $.each( [ "Width", "Height" ], function( i, name ) {
var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
type = name.toLowerCase(), type = name.toLowerCase(),
orig = { orig = {
innerWidth: $.fn.innerWidth, innerWidth: $.fn.innerWidth,
innerHeight: $.fn.innerHeight, innerHeight: $.fn.innerHeight,
outerWidth: $.fn.outerWidth, outerWidth: $.fn.outerWidth,
outerHeight: $.fn.outerHeight outerHeight: $.fn.outerHeight
}; };
function reduce( elem, size, border, margin ) { function reduce( elem, size, border, margin ) {
$.each( side, function() { $.each( side, function() {
size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0; size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
if ( border ) { if ( border ) {
size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0; size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
} }
if ( margin ) { if ( margin ) {
size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0; size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
} }
}); });
return size; return size;
} }
$.fn[ "inner" + name ] = function( size ) { $.fn[ "inner" + name ] = function( size ) {
if ( size === undefined ) { if ( size === undefined ) {
return orig[ "inner" + name ].call( this ); return orig[ "inner" + name ].call( this );
} }
return this.each(function() { return this.each(function() {
$( this ).css( type, reduce( this, size ) + "px" ); $( this ).css( type, reduce( this, size ) + "px" );
}); });
}; };
$.fn[ "outer" + name] = function( size, margin ) { $.fn[ "outer" + name] = function( size, margin ) {
if ( typeof size !== "number" ) { if ( typeof size !== "number" ) {
return orig[ "outer" + name ].call( this, size ); return orig[ "outer" + name ].call( this, size );
} }
return this.each(function() { return this.each(function() {
$( this).css( type, reduce( this, size, true, margin ) + "px" ); $( this).css( type, reduce( this, size, true, margin ) + "px" );
}); });
}; };
}); });
// selectors // selectors
function focusable( element, isTabIndexNotNaN ) { function focusable( element, isTabIndexNotNaN ) {
var nodeName = element.nodeName.toLowerCase(); var nodeName = element.nodeName.toLowerCase();
if ( "area" === nodeName ) { if ( "area" === nodeName ) {
var map = element.parentNode, var map = element.parentNode,
mapName = map.name, mapName = map.name,
img; img;
if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
return false; return false;
} }
img = $( "img[usemap=#" + mapName + "]" )[0]; img = $( "img[usemap=#" + mapName + "]" )[0];
return !!img && visible( img ); return !!img && visible( img );
} }
return ( /input|select|textarea|button|object/.test( nodeName ) return ( /input|select|textarea|button|object/.test( nodeName )
? !element.disabled ? !element.disabled
: "a" == nodeName : "a" == nodeName
? element.href || isTabIndexNotNaN ? element.href || isTabIndexNotNaN
: isTabIndexNotNaN) : isTabIndexNotNaN)
// the element and all of its ancestors must be visible // the element and all of its ancestors must be visible
&& visible( element ); && visible( element );
} }
function visible( element ) { function visible( element ) {
return !$( element ).parents().andSelf().filter(function() { return !$( element ).parents().andSelf().filter(function() {
return $.curCSS( this, "visibility" ) === "hidden" || return $.curCSS( this, "visibility" ) === "hidden" ||
$.expr.filters.hidden( this ); $.expr.filters.hidden( this );
}).length; }).length;
} }
$.extend( $.expr[ ":" ], { $.extend( $.expr[ ":" ], {
data: function( elem, i, match ) { data: function( elem, i, match ) {
return !!$.data( elem, match[ 3 ] ); return !!$.data( elem, match[ 3 ] );
}, },
focusable: function( element ) { focusable: function( element ) {
return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
}, },
tabbable: function( element ) { tabbable: function( element ) {
var tabIndex = $.attr( element, "tabindex" ), var tabIndex = $.attr( element, "tabindex" ),
isTabIndexNaN = isNaN( tabIndex ); isTabIndexNaN = isNaN( tabIndex );
return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
} }
}); });
// support // support
$(function() { $(function() {
var body = document.body, var body = document.body,
div = body.appendChild( div = document.createElement( "div" ) ); div = body.appendChild( div = document.createElement( "div" ) );
$.extend( div.style, { $.extend( div.style, {
minHeight: "100px", minHeight: "100px",
height: "auto", height: "auto",
padding: 0, padding: 0,
borderWidth: 0 borderWidth: 0
}); });
$.support.minHeight = div.offsetHeight === 100; $.support.minHeight = div.offsetHeight === 100;
$.support.selectstart = "onselectstart" in div; $.support.selectstart = "onselectstart" in div;
// set display to none to avoid a layout bug in IE // set display to none to avoid a layout bug in IE
// http://dev.jquery.com/ticket/4014 // http://dev.jquery.com/ticket/4014
body.removeChild( div ).style.display = "none"; body.removeChild( div ).style.display = "none";
}); });
// deprecated // deprecated
$.extend( $.ui, { $.extend( $.ui, {
// $.ui.plugin is deprecated. Use the proxy pattern instead. // $.ui.plugin is deprecated. Use the proxy pattern instead.
plugin: { plugin: {
add: function( module, option, set ) { add: function( module, option, set ) {
var proto = $.ui[ module ].prototype; var proto = $.ui[ module ].prototype;
for ( var i in set ) { for ( var i in set ) {
proto.plugins[ i ] = proto.plugins[ i ] || []; proto.plugins[ i ] = proto.plugins[ i ] || [];
proto.plugins[ i ].push( [ option, set[ i ] ] ); proto.plugins[ i ].push( [ option, set[ i ] ] );
} }
}, },
call: function( instance, name, args ) { call: function( instance, name, args ) {
var set = instance.plugins[ name ]; var set = instance.plugins[ name ];
if ( !set || !instance.element[ 0 ].parentNode ) { if ( !set || !instance.element[ 0 ].parentNode ) {
return; return;
} }
for ( var i = 0; i < set.length; i++ ) { for ( var i = 0; i < set.length; i++ ) {
if ( instance.options[ set[ i ][ 0 ] ] ) { if ( instance.options[ set[ i ][ 0 ] ] ) {
set[ i ][ 1 ].apply( instance.element, args ); set[ i ][ 1 ].apply( instance.element, args );
} }
} }
} }
}, },
// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains() // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
contains: function( a, b ) { contains: function( a, b ) {
return document.compareDocumentPosition ? return document.compareDocumentPosition ?
a.compareDocumentPosition( b ) & 16 : a.compareDocumentPosition( b ) & 16 :
a !== b && a.contains( b ); a !== b && a.contains( b );
}, },
// only used by resizable // only used by resizable
hasScroll: function( el, a ) { hasScroll: function( el, a ) {
//If overflow is hidden, the element might have extra content, but the user wants to hide it //If overflow is hidden, the element might have extra content, but the user wants to hide it
if ( $( el ).css( "overflow" ) === "hidden") { if ( $( el ).css( "overflow" ) === "hidden") {
return false; return false;
} }
var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
has = false; has = false;
if ( el[ scroll ] > 0 ) { if ( el[ scroll ] > 0 ) {
return true; return true;
} }
// TODO: determine which cases actually cause this to happen // TODO: determine which cases actually cause this to happen
// if the element doesn't have the scroll set, see if it's possible to // if the element doesn't have the scroll set, see if it's possible to
// set the scroll // set the scroll
el[ scroll ] = 1; el[ scroll ] = 1;
has = ( el[ scroll ] > 0 ); has = ( el[ scroll ] > 0 );
el[ scroll ] = 0; el[ scroll ] = 0;
return has; return has;
}, },
// these are odd functions, fix the API or move into individual plugins // these are odd functions, fix the API or move into individual plugins
isOverAxis: function( x, reference, size ) { isOverAxis: function( x, reference, size ) {
//Determines when x coordinate is over "b" element axis //Determines when x coordinate is over "b" element axis
return ( x > reference ) && ( x < ( reference + size ) ); return ( x > reference ) && ( x < ( reference + size ) );
}, },
isOver: function( y, x, top, left, height, width ) { isOver: function( y, x, top, left, height, width ) {
//Determines when x, y coordinates is over "b" element //Determines when x, y coordinates is over "b" element
return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width ); return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
} }
}); });
})( jQuery ); })( jQuery );

File diff suppressed because it is too large Load Diff

View File

@ -1,296 +1,296 @@
/* /*
* jQuery UI Droppable 1.8.16 * jQuery UI Droppable 1.8.16
* *
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses. * Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license * http://jquery.org/license
* *
* http://docs.jquery.com/UI/Droppables * http://docs.jquery.com/UI/Droppables
* *
* Depends: * Depends:
* jquery.ui.core.js * jquery.ui.core.js
* jquery.ui.widget.js * jquery.ui.widget.js
* jquery.ui.mouse.js * jquery.ui.mouse.js
* jquery.ui.draggable.js * jquery.ui.draggable.js
*/ */
(function( $, undefined ) { (function( $, undefined ) {
$.widget("ui.droppable", { $.widget("ui.droppable", {
widgetEventPrefix: "drop", widgetEventPrefix: "drop",
options: { options: {
accept: '*', accept: '*',
activeClass: false, activeClass: false,
addClasses: true, addClasses: true,
greedy: false, greedy: false,
hoverClass: false, hoverClass: false,
scope: 'default', scope: 'default',
tolerance: 'intersect' tolerance: 'intersect'
}, },
_create: function() { _create: function() {
var o = this.options, accept = o.accept; var o = this.options, accept = o.accept;
this.isover = 0; this.isout = 1; this.isover = 0; this.isout = 1;
this.accept = $.isFunction(accept) ? accept : function(d) { this.accept = $.isFunction(accept) ? accept : function(d) {
return d.is(accept); return d.is(accept);
}; };
//Store the droppable's proportions //Store the droppable's proportions
this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
// Add the reference and positions to the manager // Add the reference and positions to the manager
$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
$.ui.ddmanager.droppables[o.scope].push(this); $.ui.ddmanager.droppables[o.scope].push(this);
(o.addClasses && this.element.addClass("ui-droppable")); (o.addClasses && this.element.addClass("ui-droppable"));
}, },
destroy: function() { destroy: function() {
var drop = $.ui.ddmanager.droppables[this.options.scope]; var drop = $.ui.ddmanager.droppables[this.options.scope];
for ( var i = 0; i < drop.length; i++ ) for ( var i = 0; i < drop.length; i++ )
if ( drop[i] == this ) if ( drop[i] == this )
drop.splice(i, 1); drop.splice(i, 1);
this.element this.element
.removeClass("ui-droppable ui-droppable-disabled") .removeClass("ui-droppable ui-droppable-disabled")
.removeData("droppable") .removeData("droppable")
.unbind(".droppable"); .unbind(".droppable");
return this; return this;
}, },
_setOption: function(key, value) { _setOption: function(key, value) {
if(key == 'accept') { if(key == 'accept') {
this.accept = $.isFunction(value) ? value : function(d) { this.accept = $.isFunction(value) ? value : function(d) {
return d.is(value); return d.is(value);
}; };
} }
$.Widget.prototype._setOption.apply(this, arguments); $.Widget.prototype._setOption.apply(this, arguments);
}, },
_activate: function(event) { _activate: function(event) {
var draggable = $.ui.ddmanager.current; var draggable = $.ui.ddmanager.current;
if(this.options.activeClass) this.element.addClass(this.options.activeClass); if(this.options.activeClass) this.element.addClass(this.options.activeClass);
(draggable && this._trigger('activate', event, this.ui(draggable))); (draggable && this._trigger('activate', event, this.ui(draggable)));
}, },
_deactivate: function(event) { _deactivate: function(event) {
var draggable = $.ui.ddmanager.current; var draggable = $.ui.ddmanager.current;
if(this.options.activeClass) this.element.removeClass(this.options.activeClass); if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
(draggable && this._trigger('deactivate', event, this.ui(draggable))); (draggable && this._trigger('deactivate', event, this.ui(draggable)));
}, },
_over: function(event) { _over: function(event) {
var draggable = $.ui.ddmanager.current; var draggable = $.ui.ddmanager.current;
if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
if(this.options.hoverClass) this.element.addClass(this.options.hoverClass); if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
this._trigger('over', event, this.ui(draggable)); this._trigger('over', event, this.ui(draggable));
} }
}, },
_out: function(event) { _out: function(event) {
var draggable = $.ui.ddmanager.current; var draggable = $.ui.ddmanager.current;
if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
this._trigger('out', event, this.ui(draggable)); this._trigger('out', event, this.ui(draggable));
} }
}, },
_drop: function(event,custom) { _drop: function(event,custom) {
var draggable = custom || $.ui.ddmanager.current; var draggable = custom || $.ui.ddmanager.current;
if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
var childrenIntersection = false; var childrenIntersection = false;
this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() { this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
var inst = $.data(this, 'droppable'); var inst = $.data(this, 'droppable');
if( if(
inst.options.greedy inst.options.greedy
&& !inst.options.disabled && !inst.options.disabled
&& inst.options.scope == draggable.options.scope && inst.options.scope == draggable.options.scope
&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
) { childrenIntersection = true; return false; } ) { childrenIntersection = true; return false; }
}); });
if(childrenIntersection) return false; if(childrenIntersection) return false;
if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
if(this.options.activeClass) this.element.removeClass(this.options.activeClass); if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
this._trigger('drop', event, this.ui(draggable)); this._trigger('drop', event, this.ui(draggable));
return this.element; return this.element;
} }
return false; return false;
}, },
ui: function(c) { ui: function(c) {
return { return {
draggable: (c.currentItem || c.element), draggable: (c.currentItem || c.element),
helper: c.helper, helper: c.helper,
position: c.position, position: c.position,
offset: c.positionAbs offset: c.positionAbs
}; };
} }
}); });
$.extend($.ui.droppable, { $.extend($.ui.droppable, {
version: "1.8.16" version: "1.8.16"
}); });
$.ui.intersect = function(draggable, droppable, toleranceMode) { $.ui.intersect = function(draggable, droppable, toleranceMode) {
if (!droppable.offset) return false; if (!droppable.offset) return false;
var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
var l = droppable.offset.left, r = l + droppable.proportions.width, var l = droppable.offset.left, r = l + droppable.proportions.width,
t = droppable.offset.top, b = t + droppable.proportions.height; t = droppable.offset.top, b = t + droppable.proportions.height;
switch (toleranceMode) { switch (toleranceMode) {
case 'fit': case 'fit':
return (l <= x1 && x2 <= r return (l <= x1 && x2 <= r
&& t <= y1 && y2 <= b); && t <= y1 && y2 <= b);
break; break;
case 'intersect': case 'intersect':
return (l < x1 + (draggable.helperProportions.width / 2) // Right Half return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
&& x2 - (draggable.helperProportions.width / 2) < r // Left Half && x2 - (draggable.helperProportions.width / 2) < r // Left Half
&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
break; break;
case 'pointer': case 'pointer':
var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left), var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top), draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width); isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
return isOver; return isOver;
break; break;
case 'touch': case 'touch':
return ( return (
(y1 >= t && y1 <= b) || // Top edge touching (y1 >= t && y1 <= b) || // Top edge touching
(y2 >= t && y2 <= b) || // Bottom edge touching (y2 >= t && y2 <= b) || // Bottom edge touching
(y1 < t && y2 > b) // Surrounded vertically (y1 < t && y2 > b) // Surrounded vertically
) && ( ) && (
(x1 >= l && x1 <= r) || // Left edge touching (x1 >= l && x1 <= r) || // Left edge touching
(x2 >= l && x2 <= r) || // Right edge touching (x2 >= l && x2 <= r) || // Right edge touching
(x1 < l && x2 > r) // Surrounded horizontally (x1 < l && x2 > r) // Surrounded horizontally
); );
break; break;
default: default:
return false; return false;
break; break;
} }
}; };
/* /*
This manager tracks offsets of draggables and droppables This manager tracks offsets of draggables and droppables
*/ */
$.ui.ddmanager = { $.ui.ddmanager = {
current: null, current: null,
droppables: { 'default': [] }, droppables: { 'default': [] },
prepareOffsets: function(t, event) { prepareOffsets: function(t, event) {
var m = $.ui.ddmanager.droppables[t.options.scope] || []; var m = $.ui.ddmanager.droppables[t.options.scope] || [];
var type = event ? event.type : null; // workaround for #2317 var type = event ? event.type : null; // workaround for #2317
var list = (t.currentItem || t.element).find(":data(droppable)").andSelf(); var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
droppablesLoop: for (var i = 0; i < m.length; i++) { droppablesLoop: for (var i = 0; i < m.length; i++) {
if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted
for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
m[i].offset = m[i].element.offset(); m[i].offset = m[i].element.offset();
m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight }; m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
} }
}, },
drop: function(draggable, event) { drop: function(draggable, event) {
var dropped = false; var dropped = false;
$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
if(!this.options) return; if(!this.options) return;
if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
dropped = dropped || this._drop.call(this, event); dropped = dropped || this._drop.call(this, event);
if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
this.isout = 1; this.isover = 0; this.isout = 1; this.isover = 0;
this._deactivate.call(this, event); this._deactivate.call(this, event);
} }
}); });
return dropped; return dropped;
}, },
dragStart: function( draggable, event ) { dragStart: function( draggable, event ) {
//Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() { draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() {
if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
}); });
}, },
drag: function(draggable, event) { drag: function(draggable, event) {
//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event); if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
//Run through all droppables and check their positions based on specific tolerance options //Run through all droppables and check their positions based on specific tolerance options
$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
if(this.options.disabled || this.greedyChild || !this.visible) return; if(this.options.disabled || this.greedyChild || !this.visible) return;
var intersects = $.ui.intersect(draggable, this, this.options.tolerance); var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null); var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
if(!c) return; if(!c) return;
var parentInstance; var parentInstance;
if (this.options.greedy) { if (this.options.greedy) {
var parent = this.element.parents(':data(droppable):eq(0)'); var parent = this.element.parents(':data(droppable):eq(0)');
if (parent.length) { if (parent.length) {
parentInstance = $.data(parent[0], 'droppable'); parentInstance = $.data(parent[0], 'droppable');
parentInstance.greedyChild = (c == 'isover' ? 1 : 0); parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
} }
} }
// we just moved into a greedy child // we just moved into a greedy child
if (parentInstance && c == 'isover') { if (parentInstance && c == 'isover') {
parentInstance['isover'] = 0; parentInstance['isover'] = 0;
parentInstance['isout'] = 1; parentInstance['isout'] = 1;
parentInstance._out.call(parentInstance, event); parentInstance._out.call(parentInstance, event);
} }
this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0; this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
this[c == "isover" ? "_over" : "_out"].call(this, event); this[c == "isover" ? "_over" : "_out"].call(this, event);
// we just moved out of a greedy child // we just moved out of a greedy child
if (parentInstance && c == 'isout') { if (parentInstance && c == 'isout') {
parentInstance['isout'] = 0; parentInstance['isout'] = 0;
parentInstance['isover'] = 1; parentInstance['isover'] = 1;
parentInstance._over.call(parentInstance, event); parentInstance._over.call(parentInstance, event);
} }
}); });
}, },
dragStop: function( draggable, event ) { dragStop: function( draggable, event ) {
draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" ); draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" );
//Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
} }
}; };
})(jQuery); })(jQuery);

View File

@ -1,162 +1,162 @@
/*! /*!
* jQuery UI Mouse 1.8.16 * jQuery UI Mouse 1.8.16
* *
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses. * Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license * http://jquery.org/license
* *
* http://docs.jquery.com/UI/Mouse * http://docs.jquery.com/UI/Mouse
* *
* Depends: * Depends:
* jquery.ui.widget.js * jquery.ui.widget.js
*/ */
(function( $, undefined ) { (function( $, undefined ) {
var mouseHandled = false; var mouseHandled = false;
$( document ).mouseup( function( e ) { $( document ).mouseup( function( e ) {
mouseHandled = false; mouseHandled = false;
}); });
$.widget("ui.mouse", { $.widget("ui.mouse", {
options: { options: {
cancel: ':input,option', cancel: ':input,option',
distance: 1, distance: 1,
delay: 0 delay: 0
}, },
_mouseInit: function() { _mouseInit: function() {
var self = this; var self = this;
this.element this.element
.bind('mousedown.'+this.widgetName, function(event) { .bind('mousedown.'+this.widgetName, function(event) {
return self._mouseDown(event); return self._mouseDown(event);
}) })
.bind('click.'+this.widgetName, function(event) { .bind('click.'+this.widgetName, function(event) {
if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) { if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
$.removeData(event.target, self.widgetName + '.preventClickEvent'); $.removeData(event.target, self.widgetName + '.preventClickEvent');
event.stopImmediatePropagation(); event.stopImmediatePropagation();
return false; return false;
} }
}); });
this.started = false; this.started = false;
}, },
// TODO: make sure destroying one instance of mouse doesn't mess with // TODO: make sure destroying one instance of mouse doesn't mess with
// other instances of mouse // other instances of mouse
_mouseDestroy: function() { _mouseDestroy: function() {
this.element.unbind('.'+this.widgetName); this.element.unbind('.'+this.widgetName);
}, },
_mouseDown: function(event) { _mouseDown: function(event) {
// don't let more than one widget handle mouseStart // don't let more than one widget handle mouseStart
if( mouseHandled ) { return }; if( mouseHandled ) { return };
// we may have missed mouseup (out of window) // we may have missed mouseup (out of window)
(this._mouseStarted && this._mouseUp(event)); (this._mouseStarted && this._mouseUp(event));
this._mouseDownEvent = event; this._mouseDownEvent = event;
var self = this, var self = this,
btnIsLeft = (event.which == 1), btnIsLeft = (event.which == 1),
// event.target.nodeName works around a bug in IE 8 with // event.target.nodeName works around a bug in IE 8 with
// disabled inputs (#7620) // disabled inputs (#7620)
elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
return true; return true;
} }
this.mouseDelayMet = !this.options.delay; this.mouseDelayMet = !this.options.delay;
if (!this.mouseDelayMet) { if (!this.mouseDelayMet) {
this._mouseDelayTimer = setTimeout(function() { this._mouseDelayTimer = setTimeout(function() {
self.mouseDelayMet = true; self.mouseDelayMet = true;
}, this.options.delay); }, this.options.delay);
} }
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
this._mouseStarted = (this._mouseStart(event) !== false); this._mouseStarted = (this._mouseStart(event) !== false);
if (!this._mouseStarted) { if (!this._mouseStarted) {
event.preventDefault(); event.preventDefault();
return true; return true;
} }
} }
// Click event may never have fired (Gecko & Opera) // Click event may never have fired (Gecko & Opera)
if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) { if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
$.removeData(event.target, this.widgetName + '.preventClickEvent'); $.removeData(event.target, this.widgetName + '.preventClickEvent');
} }
// these delegates are required to keep context // these delegates are required to keep context
this._mouseMoveDelegate = function(event) { this._mouseMoveDelegate = function(event) {
return self._mouseMove(event); return self._mouseMove(event);
}; };
this._mouseUpDelegate = function(event) { this._mouseUpDelegate = function(event) {
return self._mouseUp(event); return self._mouseUp(event);
}; };
$(document) $(document)
.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate) .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
.bind('mouseup.'+this.widgetName, this._mouseUpDelegate); .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
event.preventDefault(); event.preventDefault();
mouseHandled = true; mouseHandled = true;
return true; return true;
}, },
_mouseMove: function(event) { _mouseMove: function(event) {
// IE mouseup check - mouseup happened when mouse was out of window // IE mouseup check - mouseup happened when mouse was out of window
if ($.browser.msie && !(document.documentMode >= 9) && !event.button) { if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
return this._mouseUp(event); return this._mouseUp(event);
} }
if (this._mouseStarted) { if (this._mouseStarted) {
this._mouseDrag(event); this._mouseDrag(event);
return event.preventDefault(); return event.preventDefault();
} }
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
this._mouseStarted = this._mouseStarted =
(this._mouseStart(this._mouseDownEvent, event) !== false); (this._mouseStart(this._mouseDownEvent, event) !== false);
(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
} }
return !this._mouseStarted; return !this._mouseStarted;
}, },
_mouseUp: function(event) { _mouseUp: function(event) {
$(document) $(document)
.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate) .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate); .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
if (this._mouseStarted) { if (this._mouseStarted) {
this._mouseStarted = false; this._mouseStarted = false;
if (event.target == this._mouseDownEvent.target) { if (event.target == this._mouseDownEvent.target) {
$.data(event.target, this.widgetName + '.preventClickEvent', true); $.data(event.target, this.widgetName + '.preventClickEvent', true);
} }
this._mouseStop(event); this._mouseStop(event);
} }
return false; return false;
}, },
_mouseDistanceMet: function(event) { _mouseDistanceMet: function(event) {
return (Math.max( return (Math.max(
Math.abs(this._mouseDownEvent.pageX - event.pageX), Math.abs(this._mouseDownEvent.pageX - event.pageX),
Math.abs(this._mouseDownEvent.pageY - event.pageY) Math.abs(this._mouseDownEvent.pageY - event.pageY)
) >= this.options.distance ) >= this.options.distance
); );
}, },
_mouseDelayMet: function(event) { _mouseDelayMet: function(event) {
return this.mouseDelayMet; return this.mouseDelayMet;
}, },
// These are placeholder methods, to be overriden by extending plugin // These are placeholder methods, to be overriden by extending plugin
_mouseStart: function(event) {}, _mouseStart: function(event) {},
_mouseDrag: function(event) {}, _mouseDrag: function(event) {},
_mouseStop: function(event) {}, _mouseStop: function(event) {},
_mouseCapture: function(event) { return true; } _mouseCapture: function(event) { return true; }
}); });
})(jQuery); })(jQuery);

File diff suppressed because it is too large Load Diff

View File

@ -1,268 +1,268 @@
/*! /*!
* jQuery UI Widget 1.8.16 * jQuery UI Widget 1.8.16
* *
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses. * Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license * http://jquery.org/license
* *
* http://docs.jquery.com/UI/Widget * http://docs.jquery.com/UI/Widget
*/ */
(function( $, undefined ) { (function( $, undefined ) {
// jQuery 1.4+ // jQuery 1.4+
if ( $.cleanData ) { if ( $.cleanData ) {
var _cleanData = $.cleanData; var _cleanData = $.cleanData;
$.cleanData = function( elems ) { $.cleanData = function( elems ) {
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
try { try {
$( elem ).triggerHandler( "remove" ); $( elem ).triggerHandler( "remove" );
// http://bugs.jquery.com/ticket/8235 // http://bugs.jquery.com/ticket/8235
} catch( e ) {} } catch( e ) {}
} }
_cleanData( elems ); _cleanData( elems );
}; };
} else { } else {
var _remove = $.fn.remove; var _remove = $.fn.remove;
$.fn.remove = function( selector, keepData ) { $.fn.remove = function( selector, keepData ) {
return this.each(function() { return this.each(function() {
if ( !keepData ) { if ( !keepData ) {
if ( !selector || $.filter( selector, [ this ] ).length ) { if ( !selector || $.filter( selector, [ this ] ).length ) {
$( "*", this ).add( [ this ] ).each(function() { $( "*", this ).add( [ this ] ).each(function() {
try { try {
$( this ).triggerHandler( "remove" ); $( this ).triggerHandler( "remove" );
// http://bugs.jquery.com/ticket/8235 // http://bugs.jquery.com/ticket/8235
} catch( e ) {} } catch( e ) {}
}); });
} }
} }
return _remove.call( $(this), selector, keepData ); return _remove.call( $(this), selector, keepData );
}); });
}; };
} }
$.widget = function( name, base, prototype ) { $.widget = function( name, base, prototype ) {
var namespace = name.split( "." )[ 0 ], var namespace = name.split( "." )[ 0 ],
fullName; fullName;
name = name.split( "." )[ 1 ]; name = name.split( "." )[ 1 ];
fullName = namespace + "-" + name; fullName = namespace + "-" + name;
if ( !prototype ) { if ( !prototype ) {
prototype = base; prototype = base;
base = $.Widget; base = $.Widget;
} }
// create selector for plugin // create selector for plugin
$.expr[ ":" ][ fullName ] = function( elem ) { $.expr[ ":" ][ fullName ] = function( elem ) {
return !!$.data( elem, name ); return !!$.data( elem, name );
}; };
$[ namespace ] = $[ namespace ] || {}; $[ namespace ] = $[ namespace ] || {};
$[ namespace ][ name ] = function( options, element ) { $[ namespace ][ name ] = function( options, element ) {
// allow instantiation without initializing for simple inheritance // allow instantiation without initializing for simple inheritance
if ( arguments.length ) { if ( arguments.length ) {
this._createWidget( options, element ); this._createWidget( options, element );
} }
}; };
var basePrototype = new base(); var basePrototype = new base();
// we need to make the options hash a property directly on the new instance // we need to make the options hash a property directly on the new instance
// otherwise we'll modify the options hash on the prototype that we're // otherwise we'll modify the options hash on the prototype that we're
// inheriting from // inheriting from
// $.each( basePrototype, function( key, val ) { // $.each( basePrototype, function( key, val ) {
// if ( $.isPlainObject(val) ) { // if ( $.isPlainObject(val) ) {
// basePrototype[ key ] = $.extend( {}, val ); // basePrototype[ key ] = $.extend( {}, val );
// } // }
// }); // });
basePrototype.options = $.extend( true, {}, basePrototype.options ); basePrototype.options = $.extend( true, {}, basePrototype.options );
$[ namespace ][ name ].prototype = $.extend( true, basePrototype, { $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
namespace: namespace, namespace: namespace,
widgetName: name, widgetName: name,
widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
widgetBaseClass: fullName widgetBaseClass: fullName
}, prototype ); }, prototype );
$.widget.bridge( name, $[ namespace ][ name ] ); $.widget.bridge( name, $[ namespace ][ name ] );
}; };
$.widget.bridge = function( name, object ) { $.widget.bridge = function( name, object ) {
$.fn[ name ] = function( options ) { $.fn[ name ] = function( options ) {
var isMethodCall = typeof options === "string", var isMethodCall = typeof options === "string",
args = Array.prototype.slice.call( arguments, 1 ), args = Array.prototype.slice.call( arguments, 1 ),
returnValue = this; returnValue = this;
// allow multiple hashes to be passed on init // allow multiple hashes to be passed on init
options = !isMethodCall && args.length ? options = !isMethodCall && args.length ?
$.extend.apply( null, [ true, options ].concat(args) ) : $.extend.apply( null, [ true, options ].concat(args) ) :
options; options;
// prevent calls to internal methods // prevent calls to internal methods
if ( isMethodCall && options.charAt( 0 ) === "_" ) { if ( isMethodCall && options.charAt( 0 ) === "_" ) {
return returnValue; return returnValue;
} }
if ( isMethodCall ) { if ( isMethodCall ) {
this.each(function() { this.each(function() {
var instance = $.data( this, name ), var instance = $.data( this, name ),
methodValue = instance && $.isFunction( instance[options] ) ? methodValue = instance && $.isFunction( instance[options] ) ?
instance[ options ].apply( instance, args ) : instance[ options ].apply( instance, args ) :
instance; instance;
// TODO: add this back in 1.9 and use $.error() (see #5972) // TODO: add this back in 1.9 and use $.error() (see #5972)
// if ( !instance ) { // if ( !instance ) {
// throw "cannot call methods on " + name + " prior to initialization; " + // throw "cannot call methods on " + name + " prior to initialization; " +
// "attempted to call method '" + options + "'"; // "attempted to call method '" + options + "'";
// } // }
// if ( !$.isFunction( instance[options] ) ) { // if ( !$.isFunction( instance[options] ) ) {
// throw "no such method '" + options + "' for " + name + " widget instance"; // throw "no such method '" + options + "' for " + name + " widget instance";
// } // }
// var methodValue = instance[ options ].apply( instance, args ); // var methodValue = instance[ options ].apply( instance, args );
if ( methodValue !== instance && methodValue !== undefined ) { if ( methodValue !== instance && methodValue !== undefined ) {
returnValue = methodValue; returnValue = methodValue;
return false; return false;
} }
}); });
} else { } else {
this.each(function() { this.each(function() {
var instance = $.data( this, name ); var instance = $.data( this, name );
if ( instance ) { if ( instance ) {
instance.option( options || {} )._init(); instance.option( options || {} )._init();
} else { } else {
$.data( this, name, new object( options, this ) ); $.data( this, name, new object( options, this ) );
} }
}); });
} }
return returnValue; return returnValue;
}; };
}; };
$.Widget = function( options, element ) { $.Widget = function( options, element ) {
// allow instantiation without initializing for simple inheritance // allow instantiation without initializing for simple inheritance
if ( arguments.length ) { if ( arguments.length ) {
this._createWidget( options, element ); this._createWidget( options, element );
} }
}; };
$.Widget.prototype = { $.Widget.prototype = {
widgetName: "widget", widgetName: "widget",
widgetEventPrefix: "", widgetEventPrefix: "",
options: { options: {
disabled: false disabled: false
}, },
_createWidget: function( options, element ) { _createWidget: function( options, element ) {
// $.widget.bridge stores the plugin instance, but we do it anyway // $.widget.bridge stores the plugin instance, but we do it anyway
// so that it's stored even before the _create function runs // so that it's stored even before the _create function runs
$.data( element, this.widgetName, this ); $.data( element, this.widgetName, this );
this.element = $( element ); this.element = $( element );
this.options = $.extend( true, {}, this.options = $.extend( true, {},
this.options, this.options,
this._getCreateOptions(), this._getCreateOptions(),
options ); options );
var self = this; var self = this;
this.element.bind( "remove." + this.widgetName, function() { this.element.bind( "remove." + this.widgetName, function() {
self.destroy(); self.destroy();
}); });
this._create(); this._create();
this._trigger( "create" ); this._trigger( "create" );
this._init(); this._init();
}, },
_getCreateOptions: function() { _getCreateOptions: function() {
return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ]; return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
}, },
_create: function() {}, _create: function() {},
_init: function() {}, _init: function() {},
destroy: function() { destroy: function() {
this.element this.element
.unbind( "." + this.widgetName ) .unbind( "." + this.widgetName )
.removeData( this.widgetName ); .removeData( this.widgetName );
this.widget() this.widget()
.unbind( "." + this.widgetName ) .unbind( "." + this.widgetName )
.removeAttr( "aria-disabled" ) .removeAttr( "aria-disabled" )
.removeClass( .removeClass(
this.widgetBaseClass + "-disabled " + this.widgetBaseClass + "-disabled " +
"ui-state-disabled" ); "ui-state-disabled" );
}, },
widget: function() { widget: function() {
return this.element; return this.element;
}, },
option: function( key, value ) { option: function( key, value ) {
var options = key; var options = key;
if ( arguments.length === 0 ) { if ( arguments.length === 0 ) {
// don't return a reference to the internal hash // don't return a reference to the internal hash
return $.extend( {}, this.options ); return $.extend( {}, this.options );
} }
if (typeof key === "string" ) { if (typeof key === "string" ) {
if ( value === undefined ) { if ( value === undefined ) {
return this.options[ key ]; return this.options[ key ];
} }
options = {}; options = {};
options[ key ] = value; options[ key ] = value;
} }
this._setOptions( options ); this._setOptions( options );
return this; return this;
}, },
_setOptions: function( options ) { _setOptions: function( options ) {
var self = this; var self = this;
$.each( options, function( key, value ) { $.each( options, function( key, value ) {
self._setOption( key, value ); self._setOption( key, value );
}); });
return this; return this;
}, },
_setOption: function( key, value ) { _setOption: function( key, value ) {
this.options[ key ] = value; this.options[ key ] = value;
if ( key === "disabled" ) { if ( key === "disabled" ) {
this.widget() this.widget()
[ value ? "addClass" : "removeClass"]( [ value ? "addClass" : "removeClass"](
this.widgetBaseClass + "-disabled" + " " + this.widgetBaseClass + "-disabled" + " " +
"ui-state-disabled" ) "ui-state-disabled" )
.attr( "aria-disabled", value ); .attr( "aria-disabled", value );
} }
return this; return this;
}, },
enable: function() { enable: function() {
return this._setOption( "disabled", false ); return this._setOption( "disabled", false );
}, },
disable: function() { disable: function() {
return this._setOption( "disabled", true ); return this._setOption( "disabled", true );
}, },
_trigger: function( type, event, data ) { _trigger: function( type, event, data ) {
var callback = this.options[ type ]; var callback = this.options[ type ];
event = $.Event( event ); event = $.Event( event );
event.type = ( type === this.widgetEventPrefix ? event.type = ( type === this.widgetEventPrefix ?
type : type :
this.widgetEventPrefix + type ).toLowerCase(); this.widgetEventPrefix + type ).toLowerCase();
data = data || {}; data = data || {};
// copy original event properties over to the new event // copy original event properties over to the new event
// this would happen if we could call $.event.fix instead of $.Event // this would happen if we could call $.event.fix instead of $.Event
// but we don't have a way to force an event to be fixed multiple times // but we don't have a way to force an event to be fixed multiple times
if ( event.originalEvent ) { if ( event.originalEvent ) {
for ( var i = $.event.props.length, prop; i; ) { for ( var i = $.event.props.length, prop; i; ) {
prop = $.event.props[ --i ]; prop = $.event.props[ --i ];
event[ prop ] = event.originalEvent[ prop ]; event[ prop ] = event.originalEvent[ prop ];
} }
} }
this.element.trigger( event, data ); this.element.trigger( event, data );
return !( $.isFunction(callback) && return !( $.isFunction(callback) &&
callback.call( this.element[0], event, data ) === false || callback.call( this.element[0], event, data ) === false ||
event.isDefaultPrevented() ); event.isDefaultPrevented() );
} }
}; };
})( jQuery ); })( jQuery );

View File

@ -1,27 +1,27 @@
{% extends "admin/change_form.html" %} {% extends "admin/change_form.html" %}
{% load i18n admin_modify adminmedia %} {% load i18n admin_modify adminmedia %}
{% load url from future %} {% load url from future %}
{% block extrahead %} {% block extrahead %}
{{ block.super }} {{ block.super }}
{% url 'admin:jsi18n' as jsi18nurl %} {% url 'admin:jsi18n' as jsi18nurl %}
{% if has_sortable_tabular_inlines or has_sortable_stacked_inlines %} {% if has_sortable_tabular_inlines or has_sortable_stacked_inlines %}
{% include 'adminsortable/shared/javascript_includes.html' %} {% include 'adminsortable/shared/javascript_includes.html' %}
{% endif %} {% endif %}
{% if has_sortable_tabular_inlines %} {% if has_sortable_tabular_inlines %}
<script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/admin.sortable.tabular.inlines.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/admin.sortable.tabular.inlines.js"></script>
{% endif %} {% endif %}
{% if has_sortable_stacked_inlines %} {% if has_sortable_stacked_inlines %}
<script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.effects.core.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.effects.core.js"></script>
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block extrastyle %} {% block extrastyle %}
{{ block.super }} {{ block.super }}
<link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/forms.css" /> <link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/forms.css" />
{% if has_sortable_tabular_inlines %} {% if has_sortable_tabular_inlines %}
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}adminsortable/css/admin.sortable.tabular.inline.css" /> <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}adminsortable/css/admin.sortable.tabular.inline.css" />
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View File

@ -1,85 +1,85 @@
{% load i18n adminmedia %} {% load i18n adminmedia %}
<div class="inline-group" id="{{ inline_admin_formset.formset.prefix }}-group"> <div class="inline-group" id="{{ inline_admin_formset.formset.prefix }}-group">
<h2>{{ inline_admin_formset.opts.verbose_name_plural|title }} {% if inline_admin_formset.opts.is_sortable %} - drag and drop to change order{% endif %}</h2> <h2>{{ inline_admin_formset.opts.verbose_name_plural|title }} {% if inline_admin_formset.opts.is_sortable %} - drag and drop to change order{% endif %}</h2>
{{ inline_admin_formset.formset.management_form }} {{ inline_admin_formset.formset.management_form }}
{{ inline_admin_formset.formset.non_form_errors }} {{ inline_admin_formset.formset.non_form_errors }}
{% for inline_admin_form in inline_admin_formset %}<div class="inline-related{% if forloop.last %} empty-form last-related{% endif %}" id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}"> {% for inline_admin_form in inline_admin_formset %}<div class="inline-related{% if forloop.last %} empty-form last-related{% endif %}" id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}">
<h3><b>{{ inline_admin_formset.opts.verbose_name|title }}:</b>&nbsp;<span class="inline_label">{% if inline_admin_form.original %}{{ inline_admin_form.original }}{% else %}#{{ forloop.counter }}{% endif %}</span> <h3><b>{{ inline_admin_formset.opts.verbose_name|title }}:</b>&nbsp;<span class="inline_label">{% if inline_admin_form.original %}{{ inline_admin_form.original }}{% else %}#{{ forloop.counter }}{% endif %}</span>
{% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original_content_type_id }}/{{ inline_admin_form.original.id }}/">{% trans "View on site" %}</a>{% endif %} {% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original_content_type_id }}/{{ inline_admin_form.original.id }}/">{% trans "View on site" %}</a>{% endif %}
{% if inline_admin_formset.formset.can_delete and inline_admin_form.original %}<span class="delete">{{ inline_admin_form.deletion_field.field }} {{ inline_admin_form.deletion_field.label_tag }}</span>{% endif %} {% if inline_admin_formset.formset.can_delete and inline_admin_form.original %}<span class="delete">{{ inline_admin_form.deletion_field.field }} {{ inline_admin_form.deletion_field.label_tag }}</span>{% endif %}
</h3> </h3>
{% if inline_admin_form.form.non_field_errors %}{{ inline_admin_form.form.non_field_errors }}{% endif %} {% if inline_admin_form.form.non_field_errors %}{{ inline_admin_form.form.non_field_errors }}{% endif %}
{% for fieldset in inline_admin_form %} {% for fieldset in inline_admin_form %}
{% include "admin/includes/fieldset.html" %} {% include "admin/includes/fieldset.html" %}
{% endfor %} {% endfor %}
{% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %} {% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
{{ inline_admin_form.fk_field.field }} {{ inline_admin_form.fk_field.field }}
{% if inline_admin_form.original %} {% if inline_admin_form.original %}
<input type="hidden" name="admin_sorting_url" value="{% url admin:admin_do_sorting inline_admin_form.original.model_type_id %}" /> <input type="hidden" name="admin_sorting_url" value="{% url admin:admin_do_sorting inline_admin_form.original.model_type_id %}" />
{% endif %} {% endif %}
</div>{% endfor %} </div>{% endfor %}
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
(function($) { (function($) {
$(document).ready(function() { $(document).ready(function() {
var rows = "#{{ inline_admin_formset.formset.prefix }}-group .inline-related"; var rows = "#{{ inline_admin_formset.formset.prefix }}-group .inline-related";
var updateInlineLabel = function(row) { var updateInlineLabel = function(row) {
$(rows).find(".inline_label").each(function(i) { $(rows).find(".inline_label").each(function(i) {
var count = i + 1; var count = i + 1;
$(this).html($(this).html().replace(/(#\d+)/g, "#" + count)); $(this).html($(this).html().replace(/(#\d+)/g, "#" + count));
}); });
} }
var reinitDateTimeShortCuts = function() { var reinitDateTimeShortCuts = function() {
// Reinitialize the calendar and clock widgets by force, yuck. // Reinitialize the calendar and clock widgets by force, yuck.
if (typeof DateTimeShortcuts != "undefined") { if (typeof DateTimeShortcuts != "undefined") {
$(".datetimeshortcuts").remove(); $(".datetimeshortcuts").remove();
DateTimeShortcuts.init(); DateTimeShortcuts.init();
} }
} }
var updateSelectFilter = function() { var updateSelectFilter = function() {
// If any SelectFilter widgets were added, instantiate a new instance. // If any SelectFilter widgets were added, instantiate a new instance.
if (typeof SelectFilter != "undefined"){ if (typeof SelectFilter != "undefined"){
$(".selectfilter").each(function(index, value){ $(".selectfilter").each(function(index, value){
var namearr = value.name.split('-'); var namearr = value.name.split('-');
SelectFilter.init(value.id, namearr[namearr.length-1], false, "{% admin_media_prefix %}"); SelectFilter.init(value.id, namearr[namearr.length-1], false, "{% admin_media_prefix %}");
}); });
$(".selectfilterstacked").each(function(index, value){ $(".selectfilterstacked").each(function(index, value){
var namearr = value.name.split('-'); var namearr = value.name.split('-');
SelectFilter.init(value.id, namearr[namearr.length-1], true, "{% admin_media_prefix %}"); SelectFilter.init(value.id, namearr[namearr.length-1], true, "{% admin_media_prefix %}");
}); });
} }
} }
var initPrepopulatedFields = function(row) { var initPrepopulatedFields = function(row) {
row.find('.prepopulated_field').each(function() { row.find('.prepopulated_field').each(function() {
var field = $(this); var field = $(this);
var input = field.find('input, select, textarea'); var input = field.find('input, select, textarea');
var dependency_list = input.data('dependency_list') || []; var dependency_list = input.data('dependency_list') || [];
var dependencies = []; var dependencies = [];
$.each(dependency_list, function(i, field_name) { $.each(dependency_list, function(i, field_name) {
dependencies.push('#' + row.find(field_name).find('input, select, textarea').attr('id')); dependencies.push('#' + row.find(field_name).find('input, select, textarea').attr('id'));
}); });
if (dependencies.length) { if (dependencies.length) {
input.prepopulate(dependencies, input.attr('maxlength')); input.prepopulate(dependencies, input.attr('maxlength'));
} }
}); });
} }
$(rows).formset({ $(rows).formset({
prefix: "{{ inline_admin_formset.formset.prefix }}", prefix: "{{ inline_admin_formset.formset.prefix }}",
addText: "{% blocktrans with inline_admin_formset.opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}", addText: "{% blocktrans with inline_admin_formset.opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}",
formCssClass: "dynamic-{{ inline_admin_formset.formset.prefix }}", formCssClass: "dynamic-{{ inline_admin_formset.formset.prefix }}",
deleteCssClass: "inline-deletelink", deleteCssClass: "inline-deletelink",
deleteText: "{% trans "Remove" %}", deleteText: "{% trans "Remove" %}",
emptyCssClass: "empty-form", emptyCssClass: "empty-form",
removed: updateInlineLabel, removed: updateInlineLabel,
added: (function(row) { added: (function(row) {
initPrepopulatedFields(row); initPrepopulatedFields(row);
reinitDateTimeShortCuts(); reinitDateTimeShortCuts();
updateSelectFilter(); updateSelectFilter();
updateInlineLabel(row); updateInlineLabel(row);
}) })
}); });
}); });
})(django.jQuery); })(django.jQuery);
</script> </script>

View File

@ -1,132 +1,132 @@
{% load i18n adminmedia admin_modify %} {% load i18n adminmedia admin_modify %}
<div class="inline-group" id="{{ inline_admin_formset.formset.prefix }}-group"> <div class="inline-group" id="{{ inline_admin_formset.formset.prefix }}-group">
<div class="tabular inline-related {% if forloop.last %}last-related{% endif %}"> <div class="tabular inline-related {% if forloop.last %}last-related{% endif %}">
{{ inline_admin_formset.formset.management_form }} {{ inline_admin_formset.formset.management_form }}
<fieldset class="module"> <fieldset class="module">
<h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }} {% if inline_admin_formset.opts.is_sortable %} - drag and drop to change order{% endif %}</h2> <h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }} {% if inline_admin_formset.opts.is_sortable %} - drag and drop to change order{% endif %}</h2>
{{ inline_admin_formset.formset.non_form_errors }} {{ inline_admin_formset.formset.non_form_errors }}
<table> <table>
<thead><tr> <thead><tr>
{% for field in inline_admin_formset.fields %} {% for field in inline_admin_formset.fields %}
{% if not field.widget.is_hidden %} {% if not field.widget.is_hidden %}
<th{% if forloop.first %} colspan="2"{% endif %}{% if field.required %} class="required"{% endif %}>{{ field.label|capfirst }}</th> <th{% if forloop.first %} colspan="2"{% endif %}{% if field.required %} class="required"{% endif %}>{{ field.label|capfirst }}</th>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% if inline_admin_formset.formset.can_delete %}<th>{% trans "Delete?" %}</th>{% endif %} {% if inline_admin_formset.formset.can_delete %}<th>{% trans "Delete?" %}</th>{% endif %}
</tr></thead> </tr></thead>
<tbody> <tbody>
{% for inline_admin_form in inline_admin_formset %} {% for inline_admin_form in inline_admin_formset %}
{% if inline_admin_form.form.non_field_errors %} {% if inline_admin_form.form.non_field_errors %}
<tr><td colspan="{{ inline_admin_form|cell_count }}">{{ inline_admin_form.form.non_field_errors }}</td></tr> <tr><td colspan="{{ inline_admin_form|cell_count }}">{{ inline_admin_form.form.non_field_errors }}</td></tr>
{% endif %} {% endif %}
<tr class="{% cycle "row1" "row2" %} {% if inline_admin_form.original or inline_admin_form.show_url %}has_original{% endif %}{% if forloop.last %} empty-form{% endif %}" <tr class="{% cycle "row1" "row2" %} {% if inline_admin_form.original or inline_admin_form.show_url %}has_original{% endif %}{% if forloop.last %} empty-form{% endif %}"
id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}"> id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}">
<td class="original"> <td class="original">
{% if inline_admin_form.original or inline_admin_form.show_url %}<p> {% if inline_admin_form.original or inline_admin_form.show_url %}<p>
{% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %} {% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %}
{% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original_content_type_id }}/{{ inline_admin_form.original.id }}/">{% trans "View on site" %}</a>{% endif %} {% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original_content_type_id }}/{{ inline_admin_form.original.id }}/">{% trans "View on site" %}</a>{% endif %}
</p>{% endif %} </p>{% endif %}
{% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %} {% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
{{ inline_admin_form.fk_field.field }} {{ inline_admin_form.fk_field.field }}
{% spaceless %} {% spaceless %}
{% for fieldset in inline_admin_form %} {% for fieldset in inline_admin_form %}
{% for line in fieldset %} {% for line in fieldset %}
{% for field in line %} {% for field in line %}
{% if field.is_hidden %} {{ field.field }} {% endif %} {% if field.is_hidden %} {{ field.field }} {% endif %}
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}
{% endspaceless %} {% endspaceless %}
{% if inline_admin_form.original %} {% if inline_admin_form.original %}
<input type="hidden" name="admin_sorting_url" value="{% url admin:admin_do_sorting inline_admin_form.original.model_type_id %}" /> <input type="hidden" name="admin_sorting_url" value="{% url admin:admin_do_sorting inline_admin_form.original.model_type_id %}" />
{% endif %} {% endif %}
</td> </td>
{% for fieldset in inline_admin_form %} {% for fieldset in inline_admin_form %}
{% for line in fieldset %} {% for line in fieldset %}
{% for field in line %} {% for field in line %}
<td class="{{ field.field.name }}"> <td class="{{ field.field.name }}">
{% if field.is_readonly %} {% if field.is_readonly %}
<p>{{ field.contents }}</p> <p>{{ field.contents }}</p>
{% else %} {% else %}
{{ field.field.errors.as_ul }} {{ field.field.errors.as_ul }}
{{ field.field }} {{ field.field }}
{% endif %} {% endif %}
</td> </td>
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}
{% if inline_admin_formset.formset.can_delete %} {% if inline_admin_formset.formset.can_delete %}
<td class="delete">{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}</td> <td class="delete">{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}</td>
{% endif %} {% endif %}
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
</fieldset> </fieldset>
</div> </div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
(function($) { (function($) {
$(document).ready(function($) { $(document).ready(function($) {
var rows = "#{{ inline_admin_formset.formset.prefix }}-group .tabular.inline-related tbody tr"; var rows = "#{{ inline_admin_formset.formset.prefix }}-group .tabular.inline-related tbody tr";
var alternatingRows = function(row) { var alternatingRows = function(row) {
$(rows).not(".add-row").removeClass("row1 row2") $(rows).not(".add-row").removeClass("row1 row2")
.filter(":even").addClass("row1").end() .filter(":even").addClass("row1").end()
.filter(rows + ":odd").addClass("row2"); .filter(rows + ":odd").addClass("row2");
} }
var reinitDateTimeShortCuts = function() { var reinitDateTimeShortCuts = function() {
// Reinitialize the calendar and clock widgets by force // Reinitialize the calendar and clock widgets by force
if (typeof DateTimeShortcuts != "undefined") { if (typeof DateTimeShortcuts != "undefined") {
$(".datetimeshortcuts").remove(); $(".datetimeshortcuts").remove();
DateTimeShortcuts.init(); DateTimeShortcuts.init();
} }
} }
var updateSelectFilter = function() { var updateSelectFilter = function() {
// If any SelectFilter widgets are a part of the new form, // If any SelectFilter widgets are a part of the new form,
// instantiate a new SelectFilter instance for it. // instantiate a new SelectFilter instance for it.
if (typeof SelectFilter != "undefined"){ if (typeof SelectFilter != "undefined"){
$(".selectfilter").each(function(index, value){ $(".selectfilter").each(function(index, value){
var namearr = value.name.split('-'); var namearr = value.name.split('-');
SelectFilter.init(value.id, namearr[namearr.length-1], false, "{% admin_media_prefix %}"); SelectFilter.init(value.id, namearr[namearr.length-1], false, "{% admin_media_prefix %}");
}); });
$(".selectfilterstacked").each(function(index, value){ $(".selectfilterstacked").each(function(index, value){
var namearr = value.name.split('-'); var namearr = value.name.split('-');
SelectFilter.init(value.id, namearr[namearr.length-1], true, "{% admin_media_prefix %}"); SelectFilter.init(value.id, namearr[namearr.length-1], true, "{% admin_media_prefix %}");
}); });
} }
} }
var initPrepopulatedFields = function(row) { var initPrepopulatedFields = function(row) {
row.find('.prepopulated_field').each(function() { row.find('.prepopulated_field').each(function() {
var field = $(this); var field = $(this);
var input = field.find('input, select, textarea'); var input = field.find('input, select, textarea');
var dependency_list = input.data('dependency_list') || []; var dependency_list = input.data('dependency_list') || [];
var dependencies = []; var dependencies = [];
$.each(dependency_list, function(i, field_name) { $.each(dependency_list, function(i, field_name) {
dependencies.push('#' + row.find(field_name).find('input, select, textarea').attr('id')); dependencies.push('#' + row.find(field_name).find('input, select, textarea').attr('id'));
}); });
if (dependencies.length) { if (dependencies.length) {
input.prepopulate(dependencies, input.attr('maxlength')); input.prepopulate(dependencies, input.attr('maxlength'));
} }
}); });
} }
$(rows).formset({ $(rows).formset({
prefix: "{{ inline_admin_formset.formset.prefix }}", prefix: "{{ inline_admin_formset.formset.prefix }}",
addText: "{% blocktrans with inline_admin_formset.opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}", addText: "{% blocktrans with inline_admin_formset.opts.verbose_name|title as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}",
formCssClass: "dynamic-{{ inline_admin_formset.formset.prefix }}", formCssClass: "dynamic-{{ inline_admin_formset.formset.prefix }}",
deleteCssClass: "inline-deletelink", deleteCssClass: "inline-deletelink",
deleteText: "{% trans "Remove" %}", deleteText: "{% trans "Remove" %}",
emptyCssClass: "empty-form", emptyCssClass: "empty-form",
removed: alternatingRows, removed: alternatingRows,
added: (function(row) { added: (function(row) {
initPrepopulatedFields(row); initPrepopulatedFields(row);
reinitDateTimeShortCuts(); reinitDateTimeShortCuts();
updateSelectFilter(); updateSelectFilter();
alternatingRows(row); alternatingRows(row);
}) })
}); });
}); });
})(django.jQuery); })(django.jQuery);
</script> </script>

View File

@ -1,10 +1,10 @@
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.ui.core.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.ui.core.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.ui.widget.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.ui.widget.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.ui.mouse.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.ui.mouse.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.ui.draggable.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.ui.draggable.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.ui.droppable.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.ui.droppable.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.ui.sortable.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.ui.sortable.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.effects.highlight.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/jquery.effects.highlight.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/admin.sortable.stacked.inlines.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/admin.sortable.stacked.inlines.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/admin.sortable.js"></script> <script type="text/javascript" src="{{ STATIC_URL }}adminsortable/js/admin.sortable.js"></script>

View File

View File

22
sample_project/README 100644 → 100755
View File

@ -1,12 +1,12 @@
Thanks for download django-admin-sortable. Thanks for download django-admin-sortable.
I hope it can help you out as much on your project(s) as it does on mine :) I hope it can help you out as much on your project(s) as it does on mine :)
The only url patterns that are enabled for this project are /admin The only url patterns that are enabled for this project are /admin
The username/password is: admin/admin The username/password is: admin/admin
If you still need help, please contact me at: btaylorweb@gmail.com If you still need help, please contact me at: btaylorweb@gmail.com
Kind regards, Kind regards,
Brandon Taylor Brandon Taylor
bTaylor Web bTaylor Web

0
sample_project/__init__.py 100644 → 100755
View File

BIN
sample_project/adminsortable.sqlite 100644 → 100755

Binary file not shown.

0
sample_project/app/__init__.py 100644 → 100755
View File

0
sample_project/app/admin.py 100644 → 100755
View File

View File

View File

View File

@ -1,59 +1,59 @@
# encoding: utf-8 # encoding: utf-8
import datetime import datetime
from south.db import db from south.db import db
from south.v2 import SchemaMigration from south.v2 import SchemaMigration
from django.db import models from django.db import models
class Migration(SchemaMigration): class Migration(SchemaMigration):
def forwards(self, orm): def forwards(self, orm):
# Adding model 'Note' # Adding model 'Note'
db.create_table('app_note', ( db.create_table('app_note', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('order', self.gf('django.db.models.fields.PositiveIntegerField')(default=1, db_index=True)), ('order', self.gf('django.db.models.fields.PositiveIntegerField')(default=1, db_index=True)),
('project', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['app.Project'])), ('project', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['app.Project'])),
('text', self.gf('django.db.models.fields.CharField')(max_length=100)), ('text', self.gf('django.db.models.fields.CharField')(max_length=100)),
)) ))
db.send_create_signal('app', ['Note']) db.send_create_signal('app', ['Note'])
def backwards(self, orm): def backwards(self, orm):
# Deleting model 'Note' # Deleting model 'Note'
db.delete_table('app_note') db.delete_table('app_note')
models = { models = {
'app.category': { 'app.category': {
'Meta': {'ordering': "['order', 'id']", 'object_name': 'Category'}, 'Meta': {'ordering': "['order', 'id']", 'object_name': 'Category'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'}), 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}) 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
}, },
'app.credit': { 'app.credit': {
'Meta': {'ordering': "['order', 'id']", 'object_name': 'Credit'}, 'Meta': {'ordering': "['order', 'id']", 'object_name': 'Credit'},
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30'}), 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'}), 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'}),
'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['app.Project']"}) 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['app.Project']"})
}, },
'app.note': { 'app.note': {
'Meta': {'ordering': "['order', 'id']", 'object_name': 'Note'}, 'Meta': {'ordering': "['order', 'id']", 'object_name': 'Note'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'}), 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'}),
'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['app.Project']"}), 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['app.Project']"}),
'text': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 'text': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}, },
'app.project': { 'app.project': {
'Meta': {'ordering': "['order', 'id']", 'object_name': 'Project'}, 'Meta': {'ordering': "['order', 'id']", 'object_name': 'Project'},
'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['app.Category']"}), 'category': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['app.Category']"}),
'description': ('django.db.models.fields.TextField', [], {}), 'description': ('django.db.models.fields.TextField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'}), 'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}) 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'})
} }
} }
complete_apps = ['app'] complete_apps = ['app']

View File

0
sample_project/app/models.py 100644 → 100755
View File

278
sample_project/app/tests.py 100644 → 100755
View File

@ -1,139 +1,139 @@
import httplib import httplib
import json import json
from django.contrib.auth.forms import authenticate, UserCreationForm from django.contrib.auth.forms import authenticate, UserCreationForm
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.middleware import csrf from django.middleware import csrf
from django.db import models from django.db import models
from django.template.defaultfilters import urlencode from django.template.defaultfilters import urlencode
from django.test import TestCase from django.test import TestCase
from django.test.client import Client, RequestFactory from django.test.client import Client, RequestFactory
from models import Sortable from models import Sortable
from app.models import Category from app.models import Category
class TestSortableModel(Sortable): class TestSortableModel(Sortable):
title = models.CharField(max_length=100) title = models.CharField(max_length=100)
def __unicode__(self): def __unicode__(self):
return self.title return self.title
class SortableTestCase(TestCase): class SortableTestCase(TestCase):
def setUp(self): def setUp(self):
self.client = Client() self.client = Client()
self.factory = RequestFactory() self.factory = RequestFactory()
self.user_raw_password = 'admin' self.user_raw_password = 'admin'
self.user = User.objects.create_user('admin', 'admin@admin.com', self.user = User.objects.create_user('admin', 'admin@admin.com',
self.user_raw_password) self.user_raw_password)
self.user.is_staff = True self.user.is_staff = True
self.user.is_superuser = True self.user.is_superuser = True
self.user.save() self.user.save()
def create_category(self, title='Category 1'): def create_category(self, title='Category 1'):
category = Category.objects.create(title=title) category, _ = Category.objects.get_or_create(title=title)
return category return category
def test_new_user_is_authenticated(self): def test_new_user_is_authenticated(self):
self.assertEqual(self.user.is_authenticated(), True, 'User is not authenticated') self.assertEqual(self.user.is_authenticated(), True, 'User is not authenticated')
def test_new_user_is_staff(self): def test_new_user_is_staff(self):
self.assertEqual(self.user.is_staff, True, 'User is not staff') self.assertEqual(self.user.is_staff, True, 'User is not staff')
def test_is_not_sortable(self): def test_is_not_sortable(self):
""" """
A model should only become sortable if it has more than A model should only become sortable if it has more than
record to sort. record to sort.
""" """
category = self.create_category() category = self.create_category()
self.assertFalse(Category.is_sortable(), self.assertFalse(Category.is_sortable(),
'Category only has one record. It should not be sortable.') 'Category only has one record. It should not be sortable.')
def test_is_sortable(self): def test_is_sortable(self):
category1 = self.create_category() category1 = self.create_category()
category2 = self.create_category(title='Category 2') category2 = self.create_category(title='Category 2')
self.assertTrue(Category.is_sortable(), self.assertTrue(Category.is_sortable(),
'Category has more than one record. It should be sortable.') 'Category has more than one record. It should be sortable.')
def test_save_order_incremented(self): def test_save_order_incremented(self):
category1 = self.create_category() category1 = self.create_category()
self.assertEqual(category1.order, 1, 'Category 1 order should be 1.') self.assertEqual(category1.order, 1, 'Category 1 order should be 1.')
category2 = self.create_category(title='Category 2') category2 = self.create_category(title='Category 2')
self.assertEqual(category2.order, 2, 'Category 2 order should be 2.') self.assertEqual(category2.order, 2, 'Category 2 order should be 2.')
def test_adminsortable_change_list_view(self): def test_adminsortable_change_list_view(self):
self.client.login(username=self.user.username, password=self.user_raw_password) self.client.login(username=self.user.username, password=self.user_raw_password)
response = self.client.get('/admin/app/category/sort/') response = self.client.get('/admin/app/category/sort/')
self.assertEquals(response.status_code, httplib.OK, 'Unable to reach sort view.') self.assertEquals(response.status_code, httplib.OK, 'Unable to reach sort view.')
def make_test_categories(self): def make_test_categories(self):
category1 = self.create_category() category1 = self.create_category()
category2 = self.create_category(title='Category 2') category2 = self.create_category(title='Category 2')
category3 = self.create_category(title='Category 3') category3 = self.create_category(title='Category 3')
return category1, category2, category3 return category1, category2, category3
def get_sorting_url(self): def get_sorting_url(self):
return reverse('admin:admin_do_sorting', args=(), return reverse('admin:admin_do_sorting', args=(),
kwargs={'model_type_id' : Category.model_type_id()}) kwargs={'model_type_id' : Category.model_type_id()})
def get_category_indexes(self, *categories): def get_category_indexes(self, *categories):
return {'indexes' : ','.join([str(c.id) for c in categories])} return {'indexes' : ','.join([str(c.id) for c in categories])}
def test_adminsortable_changelist_templates(self): def test_adminsortable_changelist_templates(self):
logged_in = self.client.login(username=self.user.username, password=self.user_raw_password) logged_in = self.client.login(username=self.user.username, password=self.user_raw_password)
self.assertTrue(logged_in, 'User is not logged in') self.assertTrue(logged_in, 'User is not logged in')
response = self.client.get(reverse('admin:admin_sort')) response = self.client.get(reverse('admin:admin_sort'))
self.assertEqual(response.status_code, httplib.OK, u'Admin sort request failed.') self.assertEqual(response.status_code, httplib.OK, u'Admin sort request failed.')
#assert adminsortable change list templates are used #assert adminsortable change list templates are used
template_names = [t.name for t in response.templates] template_names = [t.name for t in response.templates]
self.assertTrue('adminsortable/change_list.html' in template_names, self.assertTrue('adminsortable/change_list.html' in template_names,
u'adminsortable/change_list.html was not rendered') u'adminsortable/change_list.html was not rendered')
self.assertTrue('adminsortable/shared/javascript_includes.html' in template_names, self.assertTrue('adminsortable/shared/javascript_includes.html' in template_names,
u'JavaScript includes for adminsortable change list were not rendered') u'JavaScript includes for adminsortable change list were not rendered')
def test_adminsortable_change_list_sorting_fails_if_not_ajax(self): def test_adminsortable_change_list_sorting_fails_if_not_ajax(self):
logged_in = self.client.login(username=self.user.username, password=self.user_raw_password) logged_in = self.client.login(username=self.user.username, password=self.user_raw_password)
self.assertTrue(logged_in, 'User is not logged in') self.assertTrue(logged_in, 'User is not logged in')
category1, category2, category3 = self.make_test_categories() category1, category2, category3 = self.make_test_categories()
#make a normal POST #make a normal POST
response = self.client.post(self.get_sorting_url(), response = self.client.post(self.get_sorting_url(),
data=self.get_category_indexes(category1, category2, category3)) data=self.get_category_indexes(category1, category2, category3))
content = json.loads(response.content) content = json.loads(response.content)
self.assertFalse(content.get('objects_sorted'), u'Objects should not have been sorted. An ajax post is required.') self.assertFalse(content.get('objects_sorted'), u'Objects should not have been sorted. An ajax post is required.')
def test_adminsortable_change_list_sorting_successful(self): def test_adminsortable_change_list_sorting_successful(self):
logged_in = self.client.login(username=self.user.username, password=self.user_raw_password) logged_in = self.client.login(username=self.user.username, password=self.user_raw_password)
self.assertTrue(logged_in, 'User is not logged in') self.assertTrue(logged_in, 'User is not logged in')
#make categories #make categories
category1, category2, category3 = self.make_test_categories() category1, category2, category3 = self.make_test_categories()
#make an Ajax POST #make an Ajax POST
response = self.client.post(self.get_sorting_url(), response = self.client.post(self.get_sorting_url(),
data=self.get_category_indexes(category3, category2, category1), data=self.get_category_indexes(category3, category2, category1),
HTTP_X_REQUESTED_WITH='XMLHttpRequest') HTTP_X_REQUESTED_WITH='XMLHttpRequest')
content = json.loads(response.content) content = json.loads(response.content)
self.assertTrue(content.get('objects_sorted'), u'Objects should have been sorted.') self.assertTrue(content.get('objects_sorted'), u'Objects should have been sorted.')
#assert order is correct #assert order is correct
categories = Category.objects.all() categories = Category.objects.all()
cat1 = categories[0] cat1 = categories[0]
cat2 = categories[1] cat2 = categories[1]
cat3 = categories[2] cat3 = categories[2]
self.assertEqual(cat1.order, 1, u'First category returned should have order == 1') self.assertEqual(cat1.order, 1, u'First category returned should have order == 1')
self.assertEqual(cat1.pk, 3, u'Category ID 3 should have been first in queryset') self.assertEqual(cat1.pk, 3, u'Category ID 3 should have been first in queryset')
self.assertEqual(cat2.order, 2, u'Second category returned should have order == 2') self.assertEqual(cat2.order, 2, u'Second category returned should have order == 2')
self.assertEqual(cat2.pk, 2, u'Category ID 2 should have been second in queryset') self.assertEqual(cat2.pk, 2, u'Category ID 2 should have been second in queryset')
self.assertEqual(cat3.order, 3, u'Third category returned should have order == 3') self.assertEqual(cat3.order, 3, u'Third category returned should have order == 3')
self.assertEqual(cat3.pk, 1, u'Category ID 1 should have been third in queryset') self.assertEqual(cat3.pk, 1, u'Category ID 1 should have been third in queryset')

File diff suppressed because it is too large Load Diff

View File

@ -1,2 +1,2 @@
VERSION = (1, 0, 1) VERSION = (1, 0, 1)
__version__ = '1.0.1' __version__ = '1.0.1'

28
sample_project/appmedia/api.py 100644 → 100755
View File

@ -1,15 +1,15 @@
import os, os.path as osp import os, os.path as osp
from django.conf import settings from django.conf import settings
from django.db.models import get_apps from django.db.models import get_apps
def get_app_resource(app, path): def get_app_resource(app, path):
apps = get_apps() apps = get_apps()
for x in apps: for x in apps:
app_dir = osp.dirname(x.__file__) app_dir = osp.dirname(x.__file__)
if app == x.__name__.split('.')[-2]: if app == x.__name__.split('.')[-2]:
resource_dir = osp.join(app_dir, "resources") resource_dir = osp.join(app_dir, "resources")
asset = osp.join(resource_dir, path) asset = osp.join(resource_dir, path)
if osp.exists(asset): if osp.exists(asset):
return asset return asset
continue continue

View File

View File

@ -1,35 +1,35 @@
from django.core.management.base import LabelCommand, CommandError from django.core.management.base import LabelCommand, CommandError
from django.db.models import get_apps from django.db.models import get_apps
import os, os.path as osp import os, os.path as osp
import shutil import shutil
class Command(LabelCommand): class Command(LabelCommand):
args = '' args = ''
label = 'directory' label = 'directory'
def handle(self, *labels, **options): def handle(self, *labels, **options):
if not labels or len(labels) > 1: if not labels or len(labels) > 1:
raise CommandError('Enter one directory name.') raise CommandError('Enter one directory name.')
label = labels[0] label = labels[0]
final_dest = osp.join(os.getcwd(), label) final_dest = osp.join(os.getcwd(), label)
if osp.exists(final_dest): if osp.exists(final_dest):
raise CommandError('Directory already exists') raise CommandError('Directory already exists')
os.mkdir(final_dest) os.mkdir(final_dest)
apps = get_apps() apps = get_apps()
for x in apps: for x in apps:
app_dir = osp.dirname(x.__file__) app_dir = osp.dirname(x.__file__)
module = x.__name__ module = x.__name__
app = module.split('.')[-2] app = module.split('.')[-2]
if app == 'admin': continue if app == 'admin': continue
media_dir = osp.join(app_dir, "media", app) media_dir = osp.join(app_dir, "media", app)
if not osp.isdir(media_dir): if not osp.isdir(media_dir):
media_dir = osp.join(app_dir, "media") media_dir = osp.join(app_dir, "media")
if osp.exists(media_dir): if osp.exists(media_dir):
print "copy", media_dir, '->', osp.join(final_dest, app) print "copy", media_dir, '->', osp.join(final_dest, app)
shutil.copytree(media_dir, osp.join(final_dest, app)) shutil.copytree(media_dir, osp.join(final_dest, app))

View File

@ -1,53 +1,53 @@
from django.core.management.base import NoArgsCommand from django.core.management.base import NoArgsCommand
from django.db.models import get_apps from django.db.models import get_apps
class Command(NoArgsCommand): class Command(NoArgsCommand):
help = """ help = """
Removes all symlinks in MEDIA_ROOT and then scans all installed applications for a media folder to symlink to MEDIA_ROOT. Removes all symlinks in MEDIA_ROOT and then scans all installed applications for a media folder to symlink to MEDIA_ROOT.
If installed app has a media folder, it first attempts to symlink the contents If installed app has a media folder, it first attempts to symlink the contents
ie: app/media/app_name -> MEDIA_ROOT/app_name ie: app/media/app_name -> MEDIA_ROOT/app_name
If the symlink name already exists, it assumes the media directory is not subfoldered and attempts: If the symlink name already exists, it assumes the media directory is not subfoldered and attempts:
ie: app/media -> MEDIA_ROOT/app_name""" ie: app/media -> MEDIA_ROOT/app_name"""
def handle_noargs(self, **options): def handle_noargs(self, **options):
from django.conf import settings from django.conf import settings
import os import os
media_path = settings.MEDIA_ROOT media_path = settings.MEDIA_ROOT
print "creating symlinks for app media under %s" % media_path print "creating symlinks for app media under %s" % media_path
for d in os.listdir(media_path): for d in os.listdir(media_path):
path = os.path.join(media_path, d) path = os.path.join(media_path, d)
if os.path.islink(path): if os.path.islink(path):
os.remove(os.path.join(path)) os.remove(os.path.join(path))
print " - removed %s" % path print " - removed %s" % path
apps = get_apps() apps = get_apps()
for app in apps: for app in apps:
app_file = app.__file__ app_file = app.__file__
if os.path.splitext(app_file)[0].endswith('/__init__'): if os.path.splitext(app_file)[0].endswith('/__init__'):
# models are an folder, go one level up # models are an folder, go one level up
app_file = os.path.dirname(app_file) app_file = os.path.dirname(app_file)
app_path = os.path.dirname(app_file) app_path = os.path.dirname(app_file)
if 'media' in os.listdir(app_path) and os.path.isdir(os.path.join(app_path,'media')): if 'media' in os.listdir(app_path) and os.path.isdir(os.path.join(app_path,'media')):
module = app.__name__ module = app.__name__
app_name = module.split('.')[-2] app_name = module.split('.')[-2]
app_media = os.path.join(app_path, "media", app_name) app_media = os.path.join(app_path, "media", app_name)
if not os.path.isdir(app_media): if not os.path.isdir(app_media):
app_media = os.path.join(app_path, "media") app_media = os.path.join(app_path, "media")
try: try:
os.symlink(app_media, os.path.join(media_path, app_name)) os.symlink(app_media, os.path.join(media_path, app_name))
print " + added %s as %s" % (os.path.join(app_media), os.path.join(media_path, app_name)) print " + added %s as %s" % (os.path.join(app_media), os.path.join(media_path, app_name))
except OSError, e: except OSError, e:
if e.errno == 17: if e.errno == 17:
pass pass
print " o skipping %s" % app_media print " o skipping %s" % app_media
else: else:
raise raise
# try: # try:
# os.symlink(app_media, os.path.join(media_path,app.split('.')[-1])) # os.symlink(app_media, os.path.join(media_path,app.split('.')[-1]))
# print " + added %s as %s" % (app_media, os.path.join(media_path, app.split('.')[-1])) # print " + added %s as %s" % (app_media, os.path.join(media_path, app.split('.')[-1]))

View File

@ -1,38 +1,38 @@
from md5 import md5 from md5 import md5
from django.conf import settings from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from appmedia.BeautifulSoup import BeautifulSoup, Tag from appmedia.BeautifulSoup import BeautifulSoup, Tag
boundary = '*#*' boundary = '*#*'
class ReplaceAssets(object): class ReplaceAssets(object):
def process_response(self, request, response): def process_response(self, request, response):
if response['Content-Type'].startswith('text/html') and settings.CACHE_BACKEND not in ['', None, 'dummy:///']: if response['Content-Type'].startswith('text/html') and settings.CACHE_BACKEND not in ['', None, 'dummy:///']:
soup = BeautifulSoup(response.content) soup = BeautifulSoup(response.content)
head = soup.head head = soup.head
#[script.extract() for script in head.findAll(lambda x: x.name == 'script' and 'src' in dict(x.attrs) and x['src'].startswith(settings.MEDIA_URL) )] #[script.extract() for script in head.findAll(lambda x: x.name == 'script' and 'src' in dict(x.attrs) and x['src'].startswith(settings.MEDIA_URL) )]
#[css.extract() for css in head.findAll(lambda x: x.name == 'link' and 'href' in dict(x.attrs) and x['href'].startswith(settings.MEDIA_URL) )] #[css.extract() for css in head.findAll(lambda x: x.name == 'link' and 'href' in dict(x.attrs) and x['href'].startswith(settings.MEDIA_URL) )]
scripts = head.findAll(lambda x: x.name == 'script' and 'src' in dict(x.attrs) and x['src'].startswith(settings.MEDIA_URL) ) scripts = head.findAll(lambda x: x.name == 'script' and 'src' in dict(x.attrs) and x['src'].startswith(settings.MEDIA_URL) )
css = head.findAll(lambda x: x.name == 'link' and 'href' in dict(x.attrs) and x['href'].startswith(settings.MEDIA_URL) ) css = head.findAll(lambda x: x.name == 'link' and 'href' in dict(x.attrs) and x['href'].startswith(settings.MEDIA_URL) )
script_sources = [x['src'] for x in scripts] script_sources = [x['src'] for x in scripts]
new_script = md5(boundary.join(script_sources)).hexdigest() new_script = md5(boundary.join(script_sources)).hexdigest()
cache.set(new_script, script_sources) cache.set(new_script, script_sources)
[x.extract() for x in scripts] [x.extract() for x in scripts]
css_sources = [x['href'] for x in css] css_sources = [x['href'] for x in css]
new_css = md5(boundary.join(css_sources)).hexdigest() new_css = md5(boundary.join(css_sources)).hexdigest()
cache.set(new_css, css_sources) cache.set(new_css, css_sources)
[x.extract() for x in css] [x.extract() for x in css]
tag = Tag(soup, "script", [("type", "text/javascript"), ("src", reverse('cached_asset', kwargs={'asset':new_script+".js"}) )]) tag = Tag(soup, "script", [("type", "text/javascript"), ("src", reverse('cached_asset', kwargs={'asset':new_script+".js"}) )])
head.insert(0, tag) head.insert(0, tag)
tag = Tag(soup, "link", [("type", "text/css"), ("href", reverse('cached_asset', kwargs={'asset':new_css+".css"})), ('rel', 'stylesheet')]) tag = Tag(soup, "link", [("type", "text/css"), ("href", reverse('cached_asset', kwargs={'asset':new_css+".css"})), ('rel', 'stylesheet')])
head.insert(0, tag) head.insert(0, tag)
response.content = soup.prettify() response.content = soup.prettify()
return response return response

6
sample_project/appmedia/models.py 100644 → 100755
View File

@ -1,3 +1,3 @@
from django.db import models from django.db import models
# Create your models here. # Create your models here.

12
sample_project/appmedia/urls.py 100644 → 100755
View File

@ -1,7 +1,7 @@
from django.conf.urls.defaults import * from django.conf.urls.defaults import *
from django.conf import settings from django.conf import settings
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^cached-asset/(?P<asset>.*)$', 'appmedia.views.serve_cached_asset', name="cached_asset"), url(r'^cached-asset/(?P<asset>.*)$', 'appmedia.views.serve_cached_asset', name="cached_asset"),
(r'^(?P<app>[^/]*)/(?P<path>.*)$', 'appmedia.views.serve'), (r'^(?P<app>[^/]*)/(?P<path>.*)$', 'appmedia.views.serve'),
) )

160
sample_project/appmedia/views.py 100644 → 100755
View File

@ -1,81 +1,81 @@
import os, os.path as osp import os, os.path as osp
from django.conf import settings from django.conf import settings
from django.views.static import serve as django_serve from django.views.static import serve as django_serve
from django.views.decorators.cache import cache_page from django.views.decorators.cache import cache_page
from django.db.models import get_apps from django.db.models import get_apps
from django.core.cache import cache from django.core.cache import cache
from django.http import Http404, HttpResponse from django.http import Http404, HttpResponse
def serve(request, app, path, show_indexes=True): def serve(request, app, path, show_indexes=True):
if request.method == 'GET': if request.method == 'GET':
apps = get_apps() apps = get_apps()
for x in apps: for x in apps:
app_dir = osp.dirname(x.__file__) app_dir = osp.dirname(x.__file__)
module = x.__name__ module = x.__name__
if app == module.split('.')[-2]: #we get the models module here if app == module.split('.')[-2]: #we get the models module here
if app_dir.endswith("models"): if app_dir.endswith("models"):
# this can happen only in case when models are an directory # this can happen only in case when models are an directory
app_dir = osp.split(app_dir)[0] app_dir = osp.split(app_dir)[0]
media_dir = osp.join(app_dir, "media", app) media_dir = osp.join(app_dir, "media", app)
if not osp.isdir(media_dir): if not osp.isdir(media_dir):
media_dir = osp.join(app_dir, "media") media_dir = osp.join(app_dir, "media")
asset = osp.join(media_dir, path) asset = osp.join(media_dir, path)
if osp.exists(asset): if osp.exists(asset):
return django_serve(request, path, document_root=media_dir, show_indexes=show_indexes) return django_serve(request, path, document_root=media_dir, show_indexes=show_indexes)
#continue #continue
return django_serve(request, app+"/"+path, document_root=settings.MEDIA_ROOT, show_indexes=show_indexes) return django_serve(request, app+"/"+path, document_root=settings.MEDIA_ROOT, show_indexes=show_indexes)
elif request.method == 'POST': elif request.method == 'POST':
data = request.POST.get("data", "") data = request.POST.get("data", "")
apps = get_apps() apps = get_apps()
for x in apps: for x in apps:
app_dir = osp.dirname(x.__file__) app_dir = osp.dirname(x.__file__)
module = x.__name__ module = x.__name__
if app == module.split('.')[-2]: #we get the models module here if app == module.split('.')[-2]: #we get the models module here
media_dir = osp.join(app_dir, "media") media_dir = osp.join(app_dir, "media")
asset = osp.join(media_dir, path) asset = osp.join(media_dir, path)
if osp.exists(asset): if osp.exists(asset):
f = file(asset, 'w') f = file(asset, 'w')
for line in data.split('\n'): for line in data.split('\n'):
line.strip() line.strip()
line = line[:-1] line = line[:-1]
if line: if line:
selector, datap = line.split('{') selector, datap = line.split('{')
print >>f, selector, '{' print >>f, selector, '{'
datap.strip() datap.strip()
lines = datap.split(';') lines = datap.split(';')
if lines: if lines:
print >>f, " "+";\n ".join(lines) print >>f, " "+";\n ".join(lines)
print >>f, '}\n' print >>f, '}\n'
f.close() f.close()
return django_serve(request, path, document_root=media_dir, show_indexes=show_indexes) return django_serve(request, path, document_root=media_dir, show_indexes=show_indexes)
continue continue
def get_file(path): def get_file(path):
app = path.split('/')[2] app = path.split('/')[2]
path = "/".join(path.split('/')[3:]) path = "/".join(path.split('/')[3:])
apps = get_apps() apps = get_apps()
for x in apps: for x in apps:
app_dir = osp.dirname(x.__file__) app_dir = osp.dirname(x.__file__)
module = x.__name__ module = x.__name__
if app == module.split('.')[-2]: #we get the models module here if app == module.split('.')[-2]: #we get the models module here
media_dir = osp.join(app_dir, "media") media_dir = osp.join(app_dir, "media")
asset = osp.join(media_dir, path) asset = osp.join(media_dir, path)
if osp.exists(asset): if osp.exists(asset):
print osp.join(media_dir, path) print osp.join(media_dir, path)
return osp.join(media_dir, path) return osp.join(media_dir, path)
return osp.join(settings.MEDIA_ROOT, app+"/"+path) return osp.join(settings.MEDIA_ROOT, app+"/"+path)
@cache_page(24*60*60) @cache_page(24*60*60)
def serve_cached_asset(request, asset): def serve_cached_asset(request, asset):
name, ext = asset.split('.') name, ext = asset.split('.')
files = cache.get(name) files = cache.get(name)
if ext == 'js': if ext == 'js':
response = HttpResponse("\n".join([file(get_file(path)).read() for path in files]), mimetype="text/javascript") response = HttpResponse("\n".join([file(get_file(path)).read() for path in files]), mimetype="text/javascript")
return response return response
elif ext == 'css': elif ext == 'css':
response = HttpResponse("\n".join([file(get_file(path)).read() for path in files]), mimetype="text/css") response = HttpResponse("\n".join([file(get_file(path)).read() for path in files]), mimetype="text/css")
return response return response
raise Http404() raise Http404()

28
sample_project/manage.py 100644 → 100755
View File

@ -1,14 +1,14 @@
#!/usr/bin/env python #!/usr/bin/env python
from django.core.management import execute_manager from django.core.management import execute_manager
import imp import imp
try: try:
imp.find_module('settings') # Assumed to be in the same directory. imp.find_module('settings') # Assumed to be in the same directory.
except ImportError: except ImportError:
import sys import sys
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__) sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__)
sys.exit(1) sys.exit(1)
import settings import settings
if __name__ == "__main__": if __name__ == "__main__":
execute_manager(settings) execute_manager(settings)

319
sample_project/settings.py 100644 → 100755
View File

@ -1,159 +1,160 @@
import os import os
def map_path(directory_name): def map_path(directory_name):
return os.path.join(os.path.dirname(__file__), directory_name).replace('\\', '/') return os.path.join(os.path.dirname(__file__), directory_name).replace('\\', '/')
DEBUG = True DEBUG = True
SERVE_STATIC_MEDIA = True SERVE_STATIC_MEDIA = True
TEMPLATE_DEBUG = DEBUG TEMPLATE_DEBUG = DEBUG
ADMINS = ( ADMINS = (
) )
MANAGERS = ADMINS MANAGERS = ADMINS
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'adminsortable.sqlite', # Or path to database file if using sqlite3. 'NAME': 'adminsortable.sqlite', # Or path to database file if using sqlite3.
'USER': '', # Not used with sqlite3. 'USER': '', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3. 'PASSWORD': '', # Not used with sqlite3.
'HOST': '', # Set to empty string for localhost. Not used with sqlite3. 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '', # Set to empty string for default. Not used with sqlite3. 'PORT': '', # Set to empty string for default. Not used with sqlite3.
} }
} }
# Local time zone for this installation. Choices can be found here: # Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems. # although not all choices may be available on all operating systems.
# On Unix systems, a value of None will cause Django to use the same # On Unix systems, a value of None will cause Django to use the same
# timezone as the operating system. # timezone as the operating system.
# If running in a Windows environment this must be set to the same as your # If running in a Windows environment this must be set to the same as your
# system time zone. # system time zone.
TIME_ZONE = 'America/Chicago' TIME_ZONE = 'America/Chicago'
# Language code for this installation. All choices can be found here: # Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html # http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en-us' LANGUAGE_CODE = 'en-us'
SITE_ID = 1 SITE_ID = 1
# If you set this to False, Django will make some optimizations so as not # If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery. # to load the internationalization machinery.
USE_I18N = False USE_I18N = False
# If you set this to False, Django will not format dates, numbers and # If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale # calendars according to the current locale
USE_L10N = True USE_L10N = True
# Absolute filesystem path to the directory that will hold user-uploaded files. # Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/" # Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = map_path('static') MEDIA_ROOT = map_path('static')
# URL that handles the media served from MEDIA_ROOT. Make sure to use a # URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash. # trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/" # Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = '/static/' MEDIA_URL = '/static/'
# Absolute path to the directory static files should be collected to. # Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files # Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS. # in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/" # Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = '' STATIC_ROOT = ''
# URL prefix for static files. # URL prefix for static files.
# Example: "http://media.lawrence.com/static/" # Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/' STATIC_URL = '/static/'
# URL prefix for admin static files -- CSS, JavaScript and images. # URL prefix for admin static files -- CSS, JavaScript and images.
# Make sure to use a trailing slash. # Make sure to use a trailing slash.
# Examples: "http://foo.com/static/admin/", "/static/admin/". # Examples: "http://foo.com/static/admin/", "/static/admin/".
ADMIN_MEDIA_PREFIX = '/media/' ADMIN_MEDIA_PREFIX = '/media/'
# Additional locations of static files # Additional locations of static files
STATICFILES_DIRS = ( STATICFILES_DIRS = (
# Put strings here, like "/home/html/static" or "C:/www/django/static". # Put strings here, like "/home/html/static" or "C:/www/django/static".
# Always use forward slashes, even on Windows. # Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths. # Don't forget to use absolute paths, not relative paths.
) )
# List of finder classes that know how to find static files in # List of finder classes that know how to find static files in
# various locations. # various locations.
STATICFILES_FINDERS = ( STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder', # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
) )
# Make this unique, and don't share it with anybody. # Make this unique, and don't share it with anybody.
SECRET_KEY = 'uz-di2#4pzf77@9-+hh&lyypgg#--zk%$%l7p7h385#4u7ra98' SECRET_KEY = 'uz-di2#4pzf77@9-+hh&lyypgg#--zk%$%l7p7h385#4u7ra98'
# List of callables that know how to import templates from various sources. # List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = ( TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader', 'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader', 'django.template.loaders.app_directories.Loader',
# 'django.template.loaders.eggs.Loader', # 'django.template.loaders.eggs.Loader',
) )
MIDDLEWARE_CLASSES = ( MIDDLEWARE_CLASSES = (
'django.middleware.gzip.GZipMiddleware', 'django.middleware.gzip.GZipMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
) 'debug_toolbar.middleware.DebugToolbarMiddleware',
)
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth', TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.i18n', 'django.contrib.auth.context_processors.auth',
'django.core.context_processors.request', 'django.core.context_processors.i18n',
'django.core.context_processors.media', 'django.core.context_processors.request',
'django.core.context_processors.static', 'django.core.context_processors.media',
'django.contrib.messages.context_processors.messages', 'django.core.context_processors.static',
) 'django.contrib.messages.context_processors.messages',
)
ROOT_URLCONF = 'sample_project.urls'
ROOT_URLCONF = 'sample_project.urls'
TEMPLATE_DIRS = (
map_path('templates'), TEMPLATE_DIRS = (
) map_path('templates'),
)
INSTALLED_APPS = (
'django.contrib.auth', INSTALLED_APPS = (
'django.contrib.contenttypes', 'django.contrib.auth',
'django.contrib.sessions', 'django.contrib.contenttypes',
'django.contrib.sites', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.sites',
'django.contrib.admin', 'django.contrib.messages',
'django.contrib.admindocs', 'django.contrib.admin',
'django.contrib.admindocs',
'appmedia',
'south', 'appmedia',
'adminsortable', 'south',
'app', 'adminsortable',
) 'app',
)
# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to # A sample logging configuration. The only tangible logging
# the site admins on every HTTP 500 error. # performed by this configuration is to send an email to
# See http://docs.djangoproject.com/en/dev/topics/logging for # the site admins on every HTTP 500 error.
# more details on how to customize your logging configuration. # See http://docs.djangoproject.com/en/dev/topics/logging for
LOGGING = { # more details on how to customize your logging configuration.
'version': 1, LOGGING = {
'disable_existing_loggers': False, 'version': 1,
'handlers': { 'disable_existing_loggers': False,
'mail_admins': { 'handlers': {
'level': 'ERROR', 'mail_admins': {
'class': 'django.utils.log.AdminEmailHandler' 'level': 'ERROR',
} 'class': 'django.utils.log.AdminEmailHandler'
}, }
'loggers': { },
'django.request': { 'loggers': {
'handlers': ['mail_admins'], 'django.request': {
'level': 'ERROR', 'handlers': ['mail_admins'],
'propagate': True, 'level': 'ERROR',
}, 'propagate': True,
} },
} }
}

View File

@ -1,48 +1,48 @@
#sortable ul #sortable ul
{ {
-webkit-padding-start: 0; -webkit-padding-start: 0;
padding-left: 0; padding-left: 0;
margin-top: 0.75em; margin-top: 0.75em;
} }
#sortable ul ul #sortable ul ul
{ {
margin-left: 1em; margin-left: 1em;
} }
#sortable ul li, #sortable ul li,
#sortable ul li a #sortable ul li a
{ {
cursor: move; cursor: move;
} }
#sortable ul li #sortable ul li
{ {
overflow: auto; overflow: auto;
margin-left: 0; margin-left: 0;
display: block; display: block;
} }
#sortable .sortable #sortable .sortable
{ {
list-style: none; list-style: none;
font-weight: 800; font-weight: 800;
margin-bottom: 0.75em; margin-bottom: 0.75em;
} }
#sortable .sortable.single, #sortable .sortable.single,
#sortable ul ul a #sortable ul ul a
{ {
font-weight: 400; font-weight: 400;
} }
#sortable ul ul a #sortable ul ul a
{ {
color: #5B80B2; color: #5B80B2;
margin-bottom: 0; margin-bottom: 0;
} }
.sortable a:hover .sortable a:hover
{ {
color: #003366; color: #003366;
} }

View File

@ -1,21 +1,24 @@
jQuery(function($){ jQuery(function($){
$('.sortable').sortable({ $('.sortable').sortable({
axis : 'y', axis : 'y',
containment : 'parent', containment : 'parent',
tolerance : 'pointer', tolerance : 'pointer',
items : 'li', items : 'li',
stop : function(event, ui) stop : function(event, ui)
{ {
var indexes = Array(); var indexes = Array();
ui.item.parent().children('li').each(function(i) ui.item.parent().children('li').each(function(i)
{ {
indexes.push($(this).find(':hidden[name="pk"]').val()); indexes.push($(this).find(':hidden[name="pk"]').val());
}); });
$.ajax({ $.ajax({
url: ui.item.find('a.admin_sorting_url').attr('href'), url: ui.item.find('a.admin_sorting_url').attr('href'),
type: 'POST', type: 'POST',
data: { indexes: indexes.join(',') } data: { indexes: indexes.join(',') },
}); success: function(){
} ui.item.effect('highlight', {}, 1000);
}); }
}); });
}
});
});

View File

@ -1,32 +1,32 @@
jQuery(function($){ jQuery(function($){
if ($(':hidden[name="admin_sorting_url"]').length > 0) if ($(':hidden[name="admin_sorting_url"]').length > 0)
{ {
$('.inline-group').sortable({ $('.inline-group').sortable({
axis : 'y', axis : 'y',
containment : 'parent', containment : 'parent',
tolerance : 'pointer', tolerance : 'pointer',
items : '.inline-related', items : '.inline-related',
stop : function(event, ui) stop : function(event, ui)
{ {
var indexes = Array(); var indexes = Array();
ui.item.parent().children('.inline-related').each(function(i) ui.item.parent().children('.inline-related').each(function(i)
{ {
index_value = $(this).find(':hidden[name$="-id"]').val(); index_value = $(this).find(':hidden[name$="-id"]').val();
if (index_value != "" && index_value != undefined) if (index_value != "" && index_value != undefined)
indexes.push(index_value); indexes.push(index_value);
}); });
$.ajax({ $.ajax({
url: ui.item.parent().find(':hidden[name="admin_sorting_url"]').val(), url: ui.item.parent().find(':hidden[name="admin_sorting_url"]').val(),
type: 'POST', type: 'POST',
data: { indexes : indexes.join(',') }, data: { indexes : indexes.join(',') },
success: function() success: function()
{ {
//highlight sorted stacked inline //highlight sorted stacked inline
ui.item.parent().effect('highlight', {}, 1000); ui.item.parent().effect('highlight', {}, 1000);
} }
}); });
} }
}); });
} }
}); });

View File

@ -1,36 +1,36 @@
jQuery(function($){ jQuery(function($){
if ($(':hidden[name="admin_sorting_url"]').length > 0) if ($(':hidden[name="admin_sorting_url"]').length > 0)
{ {
var tabular_inline_rows = $('.tabular table tbody tr'); var tabular_inline_rows = $('.tabular table tbody tr');
tabular_inline_rows.addClass('sortable'); tabular_inline_rows.addClass('sortable');
$('.tabular.inline-related').sortable({ $('.tabular.inline-related').sortable({
axis : 'y', axis : 'y',
containment : 'parent', containment : 'parent',
tolerance : 'pointer', tolerance : 'pointer',
items : 'tr', items : 'tr',
stop : function(event, ui) stop : function(event, ui)
{ {
var indexes = Array(); var indexes = Array();
ui.item.parent().children('tr').each(function(i) ui.item.parent().children('tr').each(function(i)
{ {
index_value = $(this).find('.original :hidden:first').val(); index_value = $(this).find('.original :hidden:first').val();
if (index_value != "" && index_value != undefined) if (index_value != "" && index_value != undefined)
indexes.push(index_value); indexes.push(index_value);
}); });
$.ajax({ $.ajax({
url: ui.item.parent().find(':hidden[name="admin_sorting_url"]').val(), url: ui.item.parent().find(':hidden[name="admin_sorting_url"]').val(),
type: 'POST', type: 'POST',
data: { indexes : indexes.join(',') }, data: { indexes : indexes.join(',') },
success: function() success: function()
{ {
//re-stripe table //re-stripe table
tabular_inline_rows.removeClass('row1 row2'); tabular_inline_rows.removeClass('row1 row2');
$('.tabular table tbody tr:odd').addClass('row2'); $('.tabular table tbody tr:odd').addClass('row2');
$('.tabular table tbody tr:even').addClass('row1'); $('.tabular table tbody tr:even').addClass('row1');
} }
}); });
} }
}); });
} }
}); });

File diff suppressed because it is too large Load Diff

View File

@ -1,50 +1,50 @@
/* /*
* jQuery UI Effects Highlight 1.8.16 * jQuery UI Effects Highlight 1.8.16
* *
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses. * Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license * http://jquery.org/license
* *
* http://docs.jquery.com/UI/Effects/Highlight * http://docs.jquery.com/UI/Effects/Highlight
* *
* Depends: * Depends:
* jquery.effects.core.js * jquery.effects.core.js
*/ */
(function( $, undefined ) { (function( $, undefined ) {
$.effects.highlight = function(o) { $.effects.highlight = function(o) {
return this.queue(function() { return this.queue(function() {
var elem = $(this), var elem = $(this),
props = ['backgroundImage', 'backgroundColor', 'opacity'], props = ['backgroundImage', 'backgroundColor', 'opacity'],
mode = $.effects.setMode(elem, o.options.mode || 'show'), mode = $.effects.setMode(elem, o.options.mode || 'show'),
animation = { animation = {
backgroundColor: elem.css('backgroundColor') backgroundColor: elem.css('backgroundColor')
}; };
if (mode == 'hide') { if (mode == 'hide') {
animation.opacity = 0; animation.opacity = 0;
} }
$.effects.save(elem, props); $.effects.save(elem, props);
elem elem
.show() .show()
.css({ .css({
backgroundImage: 'none', backgroundImage: 'none',
backgroundColor: o.options.color || '#ffff99' backgroundColor: o.options.color || '#ffff99'
}) })
.animate(animation, { .animate(animation, {
queue: false, queue: false,
duration: o.duration, duration: o.duration,
easing: o.options.easing, easing: o.options.easing,
complete: function() { complete: function() {
(mode == 'hide' && elem.hide()); (mode == 'hide' && elem.hide());
$.effects.restore(elem, props); $.effects.restore(elem, props);
(mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter')); (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
(o.callback && o.callback.apply(this, arguments)); (o.callback && o.callback.apply(this, arguments));
elem.dequeue(); elem.dequeue();
} }
}); });
}); });
}; };
})(jQuery); })(jQuery);

View File

@ -1,314 +1,314 @@
/*! /*!
* jQuery UI 1.8.16 * jQuery UI 1.8.16
* *
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses. * Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license * http://jquery.org/license
* *
* http://docs.jquery.com/UI * http://docs.jquery.com/UI
*/ */
(function( $, undefined ) { (function( $, undefined ) {
// prevent duplicate loading // prevent duplicate loading
// this is only a problem because we proxy existing functions // this is only a problem because we proxy existing functions
// and we don't want to double proxy them // and we don't want to double proxy them
$.ui = $.ui || {}; $.ui = $.ui || {};
if ( $.ui.version ) { if ( $.ui.version ) {
return; return;
} }
$.extend( $.ui, { $.extend( $.ui, {
version: "1.8.16", version: "1.8.16",
keyCode: { keyCode: {
ALT: 18, ALT: 18,
BACKSPACE: 8, BACKSPACE: 8,
CAPS_LOCK: 20, CAPS_LOCK: 20,
COMMA: 188, COMMA: 188,
COMMAND: 91, COMMAND: 91,
COMMAND_LEFT: 91, // COMMAND COMMAND_LEFT: 91, // COMMAND
COMMAND_RIGHT: 93, COMMAND_RIGHT: 93,
CONTROL: 17, CONTROL: 17,
DELETE: 46, DELETE: 46,
DOWN: 40, DOWN: 40,
END: 35, END: 35,
ENTER: 13, ENTER: 13,
ESCAPE: 27, ESCAPE: 27,
HOME: 36, HOME: 36,
INSERT: 45, INSERT: 45,
LEFT: 37, LEFT: 37,
MENU: 93, // COMMAND_RIGHT MENU: 93, // COMMAND_RIGHT
NUMPAD_ADD: 107, NUMPAD_ADD: 107,
NUMPAD_DECIMAL: 110, NUMPAD_DECIMAL: 110,
NUMPAD_DIVIDE: 111, NUMPAD_DIVIDE: 111,
NUMPAD_ENTER: 108, NUMPAD_ENTER: 108,
NUMPAD_MULTIPLY: 106, NUMPAD_MULTIPLY: 106,
NUMPAD_SUBTRACT: 109, NUMPAD_SUBTRACT: 109,
PAGE_DOWN: 34, PAGE_DOWN: 34,
PAGE_UP: 33, PAGE_UP: 33,
PERIOD: 190, PERIOD: 190,
RIGHT: 39, RIGHT: 39,
SHIFT: 16, SHIFT: 16,
SPACE: 32, SPACE: 32,
TAB: 9, TAB: 9,
UP: 38, UP: 38,
WINDOWS: 91 // COMMAND WINDOWS: 91 // COMMAND
} }
}); });
// plugins // plugins
$.fn.extend({ $.fn.extend({
propAttr: $.fn.prop || $.fn.attr, propAttr: $.fn.prop || $.fn.attr,
_focus: $.fn.focus, _focus: $.fn.focus,
focus: function( delay, fn ) { focus: function( delay, fn ) {
return typeof delay === "number" ? return typeof delay === "number" ?
this.each(function() { this.each(function() {
var elem = this; var elem = this;
setTimeout(function() { setTimeout(function() {
$( elem ).focus(); $( elem ).focus();
if ( fn ) { if ( fn ) {
fn.call( elem ); fn.call( elem );
} }
}, delay ); }, delay );
}) : }) :
this._focus.apply( this, arguments ); this._focus.apply( this, arguments );
}, },
scrollParent: function() { scrollParent: function() {
var scrollParent; var scrollParent;
if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
scrollParent = this.parents().filter(function() { scrollParent = this.parents().filter(function() {
return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
}).eq(0); }).eq(0);
} else { } else {
scrollParent = this.parents().filter(function() { scrollParent = this.parents().filter(function() {
return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
}).eq(0); }).eq(0);
} }
return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent; return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
}, },
zIndex: function( zIndex ) { zIndex: function( zIndex ) {
if ( zIndex !== undefined ) { if ( zIndex !== undefined ) {
return this.css( "zIndex", zIndex ); return this.css( "zIndex", zIndex );
} }
if ( this.length ) { if ( this.length ) {
var elem = $( this[ 0 ] ), position, value; var elem = $( this[ 0 ] ), position, value;
while ( elem.length && elem[ 0 ] !== document ) { while ( elem.length && elem[ 0 ] !== document ) {
// Ignore z-index if position is set to a value where z-index is ignored by the browser // Ignore z-index if position is set to a value where z-index is ignored by the browser
// This makes behavior of this function consistent across browsers // This makes behavior of this function consistent across browsers
// WebKit always returns auto if the element is positioned // WebKit always returns auto if the element is positioned
position = elem.css( "position" ); position = elem.css( "position" );
if ( position === "absolute" || position === "relative" || position === "fixed" ) { if ( position === "absolute" || position === "relative" || position === "fixed" ) {
// IE returns 0 when zIndex is not specified // IE returns 0 when zIndex is not specified
// other browsers return a string // other browsers return a string
// we ignore the case of nested elements with an explicit value of 0 // we ignore the case of nested elements with an explicit value of 0
// <div style="z-index: -10;"><div style="z-index: 0;"></div></div> // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
value = parseInt( elem.css( "zIndex" ), 10 ); value = parseInt( elem.css( "zIndex" ), 10 );
if ( !isNaN( value ) && value !== 0 ) { if ( !isNaN( value ) && value !== 0 ) {
return value; return value;
} }
} }
elem = elem.parent(); elem = elem.parent();
} }
} }
return 0; return 0;
}, },
disableSelection: function() { disableSelection: function() {
return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
".ui-disableSelection", function( event ) { ".ui-disableSelection", function( event ) {
event.preventDefault(); event.preventDefault();
}); });
}, },
enableSelection: function() { enableSelection: function() {
return this.unbind( ".ui-disableSelection" ); return this.unbind( ".ui-disableSelection" );
} }
}); });
$.each( [ "Width", "Height" ], function( i, name ) { $.each( [ "Width", "Height" ], function( i, name ) {
var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
type = name.toLowerCase(), type = name.toLowerCase(),
orig = { orig = {
innerWidth: $.fn.innerWidth, innerWidth: $.fn.innerWidth,
innerHeight: $.fn.innerHeight, innerHeight: $.fn.innerHeight,
outerWidth: $.fn.outerWidth, outerWidth: $.fn.outerWidth,
outerHeight: $.fn.outerHeight outerHeight: $.fn.outerHeight
}; };
function reduce( elem, size, border, margin ) { function reduce( elem, size, border, margin ) {
$.each( side, function() { $.each( side, function() {
size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0; size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
if ( border ) { if ( border ) {
size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0; size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
} }
if ( margin ) { if ( margin ) {
size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0; size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
} }
}); });
return size; return size;
} }
$.fn[ "inner" + name ] = function( size ) { $.fn[ "inner" + name ] = function( size ) {
if ( size === undefined ) { if ( size === undefined ) {
return orig[ "inner" + name ].call( this ); return orig[ "inner" + name ].call( this );
} }
return this.each(function() { return this.each(function() {
$( this ).css( type, reduce( this, size ) + "px" ); $( this ).css( type, reduce( this, size ) + "px" );
}); });
}; };
$.fn[ "outer" + name] = function( size, margin ) { $.fn[ "outer" + name] = function( size, margin ) {
if ( typeof size !== "number" ) { if ( typeof size !== "number" ) {
return orig[ "outer" + name ].call( this, size ); return orig[ "outer" + name ].call( this, size );
} }
return this.each(function() { return this.each(function() {
$( this).css( type, reduce( this, size, true, margin ) + "px" ); $( this).css( type, reduce( this, size, true, margin ) + "px" );
}); });
}; };
}); });
// selectors // selectors
function focusable( element, isTabIndexNotNaN ) { function focusable( element, isTabIndexNotNaN ) {
var nodeName = element.nodeName.toLowerCase(); var nodeName = element.nodeName.toLowerCase();
if ( "area" === nodeName ) { if ( "area" === nodeName ) {
var map = element.parentNode, var map = element.parentNode,
mapName = map.name, mapName = map.name,
img; img;
if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
return false; return false;
} }
img = $( "img[usemap=#" + mapName + "]" )[0]; img = $( "img[usemap=#" + mapName + "]" )[0];
return !!img && visible( img ); return !!img && visible( img );
} }
return ( /input|select|textarea|button|object/.test( nodeName ) return ( /input|select|textarea|button|object/.test( nodeName )
? !element.disabled ? !element.disabled
: "a" == nodeName : "a" == nodeName
? element.href || isTabIndexNotNaN ? element.href || isTabIndexNotNaN
: isTabIndexNotNaN) : isTabIndexNotNaN)
// the element and all of its ancestors must be visible // the element and all of its ancestors must be visible
&& visible( element ); && visible( element );
} }
function visible( element ) { function visible( element ) {
return !$( element ).parents().andSelf().filter(function() { return !$( element ).parents().andSelf().filter(function() {
return $.curCSS( this, "visibility" ) === "hidden" || return $.curCSS( this, "visibility" ) === "hidden" ||
$.expr.filters.hidden( this ); $.expr.filters.hidden( this );
}).length; }).length;
} }
$.extend( $.expr[ ":" ], { $.extend( $.expr[ ":" ], {
data: function( elem, i, match ) { data: function( elem, i, match ) {
return !!$.data( elem, match[ 3 ] ); return !!$.data( elem, match[ 3 ] );
}, },
focusable: function( element ) { focusable: function( element ) {
return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
}, },
tabbable: function( element ) { tabbable: function( element ) {
var tabIndex = $.attr( element, "tabindex" ), var tabIndex = $.attr( element, "tabindex" ),
isTabIndexNaN = isNaN( tabIndex ); isTabIndexNaN = isNaN( tabIndex );
return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
} }
}); });
// support // support
$(function() { $(function() {
var body = document.body, var body = document.body,
div = body.appendChild( div = document.createElement( "div" ) ); div = body.appendChild( div = document.createElement( "div" ) );
$.extend( div.style, { $.extend( div.style, {
minHeight: "100px", minHeight: "100px",
height: "auto", height: "auto",
padding: 0, padding: 0,
borderWidth: 0 borderWidth: 0
}); });
$.support.minHeight = div.offsetHeight === 100; $.support.minHeight = div.offsetHeight === 100;
$.support.selectstart = "onselectstart" in div; $.support.selectstart = "onselectstart" in div;
// set display to none to avoid a layout bug in IE // set display to none to avoid a layout bug in IE
// http://dev.jquery.com/ticket/4014 // http://dev.jquery.com/ticket/4014
body.removeChild( div ).style.display = "none"; body.removeChild( div ).style.display = "none";
}); });
// deprecated // deprecated
$.extend( $.ui, { $.extend( $.ui, {
// $.ui.plugin is deprecated. Use the proxy pattern instead. // $.ui.plugin is deprecated. Use the proxy pattern instead.
plugin: { plugin: {
add: function( module, option, set ) { add: function( module, option, set ) {
var proto = $.ui[ module ].prototype; var proto = $.ui[ module ].prototype;
for ( var i in set ) { for ( var i in set ) {
proto.plugins[ i ] = proto.plugins[ i ] || []; proto.plugins[ i ] = proto.plugins[ i ] || [];
proto.plugins[ i ].push( [ option, set[ i ] ] ); proto.plugins[ i ].push( [ option, set[ i ] ] );
} }
}, },
call: function( instance, name, args ) { call: function( instance, name, args ) {
var set = instance.plugins[ name ]; var set = instance.plugins[ name ];
if ( !set || !instance.element[ 0 ].parentNode ) { if ( !set || !instance.element[ 0 ].parentNode ) {
return; return;
} }
for ( var i = 0; i < set.length; i++ ) { for ( var i = 0; i < set.length; i++ ) {
if ( instance.options[ set[ i ][ 0 ] ] ) { if ( instance.options[ set[ i ][ 0 ] ] ) {
set[ i ][ 1 ].apply( instance.element, args ); set[ i ][ 1 ].apply( instance.element, args );
} }
} }
} }
}, },
// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains() // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
contains: function( a, b ) { contains: function( a, b ) {
return document.compareDocumentPosition ? return document.compareDocumentPosition ?
a.compareDocumentPosition( b ) & 16 : a.compareDocumentPosition( b ) & 16 :
a !== b && a.contains( b ); a !== b && a.contains( b );
}, },
// only used by resizable // only used by resizable
hasScroll: function( el, a ) { hasScroll: function( el, a ) {
//If overflow is hidden, the element might have extra content, but the user wants to hide it //If overflow is hidden, the element might have extra content, but the user wants to hide it
if ( $( el ).css( "overflow" ) === "hidden") { if ( $( el ).css( "overflow" ) === "hidden") {
return false; return false;
} }
var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
has = false; has = false;
if ( el[ scroll ] > 0 ) { if ( el[ scroll ] > 0 ) {
return true; return true;
} }
// TODO: determine which cases actually cause this to happen // TODO: determine which cases actually cause this to happen
// if the element doesn't have the scroll set, see if it's possible to // if the element doesn't have the scroll set, see if it's possible to
// set the scroll // set the scroll
el[ scroll ] = 1; el[ scroll ] = 1;
has = ( el[ scroll ] > 0 ); has = ( el[ scroll ] > 0 );
el[ scroll ] = 0; el[ scroll ] = 0;
return has; return has;
}, },
// these are odd functions, fix the API or move into individual plugins // these are odd functions, fix the API or move into individual plugins
isOverAxis: function( x, reference, size ) { isOverAxis: function( x, reference, size ) {
//Determines when x coordinate is over "b" element axis //Determines when x coordinate is over "b" element axis
return ( x > reference ) && ( x < ( reference + size ) ); return ( x > reference ) && ( x < ( reference + size ) );
}, },
isOver: function( y, x, top, left, height, width ) { isOver: function( y, x, top, left, height, width ) {
//Determines when x, y coordinates is over "b" element //Determines when x, y coordinates is over "b" element
return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width ); return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
} }
}); });
})( jQuery ); })( jQuery );

File diff suppressed because it is too large Load Diff

View File

@ -1,296 +1,296 @@
/* /*
* jQuery UI Droppable 1.8.16 * jQuery UI Droppable 1.8.16
* *
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses. * Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license * http://jquery.org/license
* *
* http://docs.jquery.com/UI/Droppables * http://docs.jquery.com/UI/Droppables
* *
* Depends: * Depends:
* jquery.ui.core.js * jquery.ui.core.js
* jquery.ui.widget.js * jquery.ui.widget.js
* jquery.ui.mouse.js * jquery.ui.mouse.js
* jquery.ui.draggable.js * jquery.ui.draggable.js
*/ */
(function( $, undefined ) { (function( $, undefined ) {
$.widget("ui.droppable", { $.widget("ui.droppable", {
widgetEventPrefix: "drop", widgetEventPrefix: "drop",
options: { options: {
accept: '*', accept: '*',
activeClass: false, activeClass: false,
addClasses: true, addClasses: true,
greedy: false, greedy: false,
hoverClass: false, hoverClass: false,
scope: 'default', scope: 'default',
tolerance: 'intersect' tolerance: 'intersect'
}, },
_create: function() { _create: function() {
var o = this.options, accept = o.accept; var o = this.options, accept = o.accept;
this.isover = 0; this.isout = 1; this.isover = 0; this.isout = 1;
this.accept = $.isFunction(accept) ? accept : function(d) { this.accept = $.isFunction(accept) ? accept : function(d) {
return d.is(accept); return d.is(accept);
}; };
//Store the droppable's proportions //Store the droppable's proportions
this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
// Add the reference and positions to the manager // Add the reference and positions to the manager
$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
$.ui.ddmanager.droppables[o.scope].push(this); $.ui.ddmanager.droppables[o.scope].push(this);
(o.addClasses && this.element.addClass("ui-droppable")); (o.addClasses && this.element.addClass("ui-droppable"));
}, },
destroy: function() { destroy: function() {
var drop = $.ui.ddmanager.droppables[this.options.scope]; var drop = $.ui.ddmanager.droppables[this.options.scope];
for ( var i = 0; i < drop.length; i++ ) for ( var i = 0; i < drop.length; i++ )
if ( drop[i] == this ) if ( drop[i] == this )
drop.splice(i, 1); drop.splice(i, 1);
this.element this.element
.removeClass("ui-droppable ui-droppable-disabled") .removeClass("ui-droppable ui-droppable-disabled")
.removeData("droppable") .removeData("droppable")
.unbind(".droppable"); .unbind(".droppable");
return this; return this;
}, },
_setOption: function(key, value) { _setOption: function(key, value) {
if(key == 'accept') { if(key == 'accept') {
this.accept = $.isFunction(value) ? value : function(d) { this.accept = $.isFunction(value) ? value : function(d) {
return d.is(value); return d.is(value);
}; };
} }
$.Widget.prototype._setOption.apply(this, arguments); $.Widget.prototype._setOption.apply(this, arguments);
}, },
_activate: function(event) { _activate: function(event) {
var draggable = $.ui.ddmanager.current; var draggable = $.ui.ddmanager.current;
if(this.options.activeClass) this.element.addClass(this.options.activeClass); if(this.options.activeClass) this.element.addClass(this.options.activeClass);
(draggable && this._trigger('activate', event, this.ui(draggable))); (draggable && this._trigger('activate', event, this.ui(draggable)));
}, },
_deactivate: function(event) { _deactivate: function(event) {
var draggable = $.ui.ddmanager.current; var draggable = $.ui.ddmanager.current;
if(this.options.activeClass) this.element.removeClass(this.options.activeClass); if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
(draggable && this._trigger('deactivate', event, this.ui(draggable))); (draggable && this._trigger('deactivate', event, this.ui(draggable)));
}, },
_over: function(event) { _over: function(event) {
var draggable = $.ui.ddmanager.current; var draggable = $.ui.ddmanager.current;
if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
if(this.options.hoverClass) this.element.addClass(this.options.hoverClass); if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
this._trigger('over', event, this.ui(draggable)); this._trigger('over', event, this.ui(draggable));
} }
}, },
_out: function(event) { _out: function(event) {
var draggable = $.ui.ddmanager.current; var draggable = $.ui.ddmanager.current;
if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
this._trigger('out', event, this.ui(draggable)); this._trigger('out', event, this.ui(draggable));
} }
}, },
_drop: function(event,custom) { _drop: function(event,custom) {
var draggable = custom || $.ui.ddmanager.current; var draggable = custom || $.ui.ddmanager.current;
if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
var childrenIntersection = false; var childrenIntersection = false;
this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() { this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
var inst = $.data(this, 'droppable'); var inst = $.data(this, 'droppable');
if( if(
inst.options.greedy inst.options.greedy
&& !inst.options.disabled && !inst.options.disabled
&& inst.options.scope == draggable.options.scope && inst.options.scope == draggable.options.scope
&& inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
&& $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
) { childrenIntersection = true; return false; } ) { childrenIntersection = true; return false; }
}); });
if(childrenIntersection) return false; if(childrenIntersection) return false;
if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
if(this.options.activeClass) this.element.removeClass(this.options.activeClass); if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
this._trigger('drop', event, this.ui(draggable)); this._trigger('drop', event, this.ui(draggable));
return this.element; return this.element;
} }
return false; return false;
}, },
ui: function(c) { ui: function(c) {
return { return {
draggable: (c.currentItem || c.element), draggable: (c.currentItem || c.element),
helper: c.helper, helper: c.helper,
position: c.position, position: c.position,
offset: c.positionAbs offset: c.positionAbs
}; };
} }
}); });
$.extend($.ui.droppable, { $.extend($.ui.droppable, {
version: "1.8.16" version: "1.8.16"
}); });
$.ui.intersect = function(draggable, droppable, toleranceMode) { $.ui.intersect = function(draggable, droppable, toleranceMode) {
if (!droppable.offset) return false; if (!droppable.offset) return false;
var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
var l = droppable.offset.left, r = l + droppable.proportions.width, var l = droppable.offset.left, r = l + droppable.proportions.width,
t = droppable.offset.top, b = t + droppable.proportions.height; t = droppable.offset.top, b = t + droppable.proportions.height;
switch (toleranceMode) { switch (toleranceMode) {
case 'fit': case 'fit':
return (l <= x1 && x2 <= r return (l <= x1 && x2 <= r
&& t <= y1 && y2 <= b); && t <= y1 && y2 <= b);
break; break;
case 'intersect': case 'intersect':
return (l < x1 + (draggable.helperProportions.width / 2) // Right Half return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
&& x2 - (draggable.helperProportions.width / 2) < r // Left Half && x2 - (draggable.helperProportions.width / 2) < r // Left Half
&& t < y1 + (draggable.helperProportions.height / 2) // Bottom Half && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
&& y2 - (draggable.helperProportions.height / 2) < b ); // Top Half && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
break; break;
case 'pointer': case 'pointer':
var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left), var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top), draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width); isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
return isOver; return isOver;
break; break;
case 'touch': case 'touch':
return ( return (
(y1 >= t && y1 <= b) || // Top edge touching (y1 >= t && y1 <= b) || // Top edge touching
(y2 >= t && y2 <= b) || // Bottom edge touching (y2 >= t && y2 <= b) || // Bottom edge touching
(y1 < t && y2 > b) // Surrounded vertically (y1 < t && y2 > b) // Surrounded vertically
) && ( ) && (
(x1 >= l && x1 <= r) || // Left edge touching (x1 >= l && x1 <= r) || // Left edge touching
(x2 >= l && x2 <= r) || // Right edge touching (x2 >= l && x2 <= r) || // Right edge touching
(x1 < l && x2 > r) // Surrounded horizontally (x1 < l && x2 > r) // Surrounded horizontally
); );
break; break;
default: default:
return false; return false;
break; break;
} }
}; };
/* /*
This manager tracks offsets of draggables and droppables This manager tracks offsets of draggables and droppables
*/ */
$.ui.ddmanager = { $.ui.ddmanager = {
current: null, current: null,
droppables: { 'default': [] }, droppables: { 'default': [] },
prepareOffsets: function(t, event) { prepareOffsets: function(t, event) {
var m = $.ui.ddmanager.droppables[t.options.scope] || []; var m = $.ui.ddmanager.droppables[t.options.scope] || [];
var type = event ? event.type : null; // workaround for #2317 var type = event ? event.type : null; // workaround for #2317
var list = (t.currentItem || t.element).find(":data(droppable)").andSelf(); var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
droppablesLoop: for (var i = 0; i < m.length; i++) { droppablesLoop: for (var i = 0; i < m.length; i++) {
if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted
for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
m[i].offset = m[i].element.offset(); m[i].offset = m[i].element.offset();
m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight }; m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
} }
}, },
drop: function(draggable, event) { drop: function(draggable, event) {
var dropped = false; var dropped = false;
$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
if(!this.options) return; if(!this.options) return;
if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
dropped = dropped || this._drop.call(this, event); dropped = dropped || this._drop.call(this, event);
if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
this.isout = 1; this.isover = 0; this.isout = 1; this.isover = 0;
this._deactivate.call(this, event); this._deactivate.call(this, event);
} }
}); });
return dropped; return dropped;
}, },
dragStart: function( draggable, event ) { dragStart: function( draggable, event ) {
//Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() { draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() {
if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
}); });
}, },
drag: function(draggable, event) { drag: function(draggable, event) {
//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event); if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
//Run through all droppables and check their positions based on specific tolerance options //Run through all droppables and check their positions based on specific tolerance options
$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
if(this.options.disabled || this.greedyChild || !this.visible) return; if(this.options.disabled || this.greedyChild || !this.visible) return;
var intersects = $.ui.intersect(draggable, this, this.options.tolerance); var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null); var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
if(!c) return; if(!c) return;
var parentInstance; var parentInstance;
if (this.options.greedy) { if (this.options.greedy) {
var parent = this.element.parents(':data(droppable):eq(0)'); var parent = this.element.parents(':data(droppable):eq(0)');
if (parent.length) { if (parent.length) {
parentInstance = $.data(parent[0], 'droppable'); parentInstance = $.data(parent[0], 'droppable');
parentInstance.greedyChild = (c == 'isover' ? 1 : 0); parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
} }
} }
// we just moved into a greedy child // we just moved into a greedy child
if (parentInstance && c == 'isover') { if (parentInstance && c == 'isover') {
parentInstance['isover'] = 0; parentInstance['isover'] = 0;
parentInstance['isout'] = 1; parentInstance['isout'] = 1;
parentInstance._out.call(parentInstance, event); parentInstance._out.call(parentInstance, event);
} }
this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0; this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
this[c == "isover" ? "_over" : "_out"].call(this, event); this[c == "isover" ? "_over" : "_out"].call(this, event);
// we just moved out of a greedy child // we just moved out of a greedy child
if (parentInstance && c == 'isout') { if (parentInstance && c == 'isout') {
parentInstance['isout'] = 0; parentInstance['isout'] = 0;
parentInstance['isover'] = 1; parentInstance['isover'] = 1;
parentInstance._over.call(parentInstance, event); parentInstance._over.call(parentInstance, event);
} }
}); });
}, },
dragStop: function( draggable, event ) { dragStop: function( draggable, event ) {
draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" ); draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" );
//Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
} }
}; };
})(jQuery); })(jQuery);

View File

@ -1,162 +1,162 @@
/*! /*!
* jQuery UI Mouse 1.8.16 * jQuery UI Mouse 1.8.16
* *
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses. * Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license * http://jquery.org/license
* *
* http://docs.jquery.com/UI/Mouse * http://docs.jquery.com/UI/Mouse
* *
* Depends: * Depends:
* jquery.ui.widget.js * jquery.ui.widget.js
*/ */
(function( $, undefined ) { (function( $, undefined ) {
var mouseHandled = false; var mouseHandled = false;
$( document ).mouseup( function( e ) { $( document ).mouseup( function( e ) {
mouseHandled = false; mouseHandled = false;
}); });
$.widget("ui.mouse", { $.widget("ui.mouse", {
options: { options: {
cancel: ':input,option', cancel: ':input,option',
distance: 1, distance: 1,
delay: 0 delay: 0
}, },
_mouseInit: function() { _mouseInit: function() {
var self = this; var self = this;
this.element this.element
.bind('mousedown.'+this.widgetName, function(event) { .bind('mousedown.'+this.widgetName, function(event) {
return self._mouseDown(event); return self._mouseDown(event);
}) })
.bind('click.'+this.widgetName, function(event) { .bind('click.'+this.widgetName, function(event) {
if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) { if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
$.removeData(event.target, self.widgetName + '.preventClickEvent'); $.removeData(event.target, self.widgetName + '.preventClickEvent');
event.stopImmediatePropagation(); event.stopImmediatePropagation();
return false; return false;
} }
}); });
this.started = false; this.started = false;
}, },
// TODO: make sure destroying one instance of mouse doesn't mess with // TODO: make sure destroying one instance of mouse doesn't mess with
// other instances of mouse // other instances of mouse
_mouseDestroy: function() { _mouseDestroy: function() {
this.element.unbind('.'+this.widgetName); this.element.unbind('.'+this.widgetName);
}, },
_mouseDown: function(event) { _mouseDown: function(event) {
// don't let more than one widget handle mouseStart // don't let more than one widget handle mouseStart
if( mouseHandled ) { return }; if( mouseHandled ) { return };
// we may have missed mouseup (out of window) // we may have missed mouseup (out of window)
(this._mouseStarted && this._mouseUp(event)); (this._mouseStarted && this._mouseUp(event));
this._mouseDownEvent = event; this._mouseDownEvent = event;
var self = this, var self = this,
btnIsLeft = (event.which == 1), btnIsLeft = (event.which == 1),
// event.target.nodeName works around a bug in IE 8 with // event.target.nodeName works around a bug in IE 8 with
// disabled inputs (#7620) // disabled inputs (#7620)
elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
return true; return true;
} }
this.mouseDelayMet = !this.options.delay; this.mouseDelayMet = !this.options.delay;
if (!this.mouseDelayMet) { if (!this.mouseDelayMet) {
this._mouseDelayTimer = setTimeout(function() { this._mouseDelayTimer = setTimeout(function() {
self.mouseDelayMet = true; self.mouseDelayMet = true;
}, this.options.delay); }, this.options.delay);
} }
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
this._mouseStarted = (this._mouseStart(event) !== false); this._mouseStarted = (this._mouseStart(event) !== false);
if (!this._mouseStarted) { if (!this._mouseStarted) {
event.preventDefault(); event.preventDefault();
return true; return true;
} }
} }
// Click event may never have fired (Gecko & Opera) // Click event may never have fired (Gecko & Opera)
if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) { if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
$.removeData(event.target, this.widgetName + '.preventClickEvent'); $.removeData(event.target, this.widgetName + '.preventClickEvent');
} }
// these delegates are required to keep context // these delegates are required to keep context
this._mouseMoveDelegate = function(event) { this._mouseMoveDelegate = function(event) {
return self._mouseMove(event); return self._mouseMove(event);
}; };
this._mouseUpDelegate = function(event) { this._mouseUpDelegate = function(event) {
return self._mouseUp(event); return self._mouseUp(event);
}; };
$(document) $(document)
.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate) .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
.bind('mouseup.'+this.widgetName, this._mouseUpDelegate); .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
event.preventDefault(); event.preventDefault();
mouseHandled = true; mouseHandled = true;
return true; return true;
}, },
_mouseMove: function(event) { _mouseMove: function(event) {
// IE mouseup check - mouseup happened when mouse was out of window // IE mouseup check - mouseup happened when mouse was out of window
if ($.browser.msie && !(document.documentMode >= 9) && !event.button) { if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
return this._mouseUp(event); return this._mouseUp(event);
} }
if (this._mouseStarted) { if (this._mouseStarted) {
this._mouseDrag(event); this._mouseDrag(event);
return event.preventDefault(); return event.preventDefault();
} }
if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
this._mouseStarted = this._mouseStarted =
(this._mouseStart(this._mouseDownEvent, event) !== false); (this._mouseStart(this._mouseDownEvent, event) !== false);
(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
} }
return !this._mouseStarted; return !this._mouseStarted;
}, },
_mouseUp: function(event) { _mouseUp: function(event) {
$(document) $(document)
.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate) .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate); .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
if (this._mouseStarted) { if (this._mouseStarted) {
this._mouseStarted = false; this._mouseStarted = false;
if (event.target == this._mouseDownEvent.target) { if (event.target == this._mouseDownEvent.target) {
$.data(event.target, this.widgetName + '.preventClickEvent', true); $.data(event.target, this.widgetName + '.preventClickEvent', true);
} }
this._mouseStop(event); this._mouseStop(event);
} }
return false; return false;
}, },
_mouseDistanceMet: function(event) { _mouseDistanceMet: function(event) {
return (Math.max( return (Math.max(
Math.abs(this._mouseDownEvent.pageX - event.pageX), Math.abs(this._mouseDownEvent.pageX - event.pageX),
Math.abs(this._mouseDownEvent.pageY - event.pageY) Math.abs(this._mouseDownEvent.pageY - event.pageY)
) >= this.options.distance ) >= this.options.distance
); );
}, },
_mouseDelayMet: function(event) { _mouseDelayMet: function(event) {
return this.mouseDelayMet; return this.mouseDelayMet;
}, },
// These are placeholder methods, to be overriden by extending plugin // These are placeholder methods, to be overriden by extending plugin
_mouseStart: function(event) {}, _mouseStart: function(event) {},
_mouseDrag: function(event) {}, _mouseDrag: function(event) {},
_mouseStop: function(event) {}, _mouseStop: function(event) {},
_mouseCapture: function(event) { return true; } _mouseCapture: function(event) { return true; }
}); });
})(jQuery); })(jQuery);

File diff suppressed because it is too large Load Diff

View File

@ -1,268 +1,268 @@
/*! /*!
* jQuery UI Widget 1.8.16 * jQuery UI Widget 1.8.16
* *
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses. * Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license * http://jquery.org/license
* *
* http://docs.jquery.com/UI/Widget * http://docs.jquery.com/UI/Widget
*/ */
(function( $, undefined ) { (function( $, undefined ) {
// jQuery 1.4+ // jQuery 1.4+
if ( $.cleanData ) { if ( $.cleanData ) {
var _cleanData = $.cleanData; var _cleanData = $.cleanData;
$.cleanData = function( elems ) { $.cleanData = function( elems ) {
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
try { try {
$( elem ).triggerHandler( "remove" ); $( elem ).triggerHandler( "remove" );
// http://bugs.jquery.com/ticket/8235 // http://bugs.jquery.com/ticket/8235
} catch( e ) {} } catch( e ) {}
} }
_cleanData( elems ); _cleanData( elems );
}; };
} else { } else {
var _remove = $.fn.remove; var _remove = $.fn.remove;
$.fn.remove = function( selector, keepData ) { $.fn.remove = function( selector, keepData ) {
return this.each(function() { return this.each(function() {
if ( !keepData ) { if ( !keepData ) {
if ( !selector || $.filter( selector, [ this ] ).length ) { if ( !selector || $.filter( selector, [ this ] ).length ) {
$( "*", this ).add( [ this ] ).each(function() { $( "*", this ).add( [ this ] ).each(function() {
try { try {
$( this ).triggerHandler( "remove" ); $( this ).triggerHandler( "remove" );
// http://bugs.jquery.com/ticket/8235 // http://bugs.jquery.com/ticket/8235
} catch( e ) {} } catch( e ) {}
}); });
} }
} }
return _remove.call( $(this), selector, keepData ); return _remove.call( $(this), selector, keepData );
}); });
}; };
} }
$.widget = function( name, base, prototype ) { $.widget = function( name, base, prototype ) {
var namespace = name.split( "." )[ 0 ], var namespace = name.split( "." )[ 0 ],
fullName; fullName;
name = name.split( "." )[ 1 ]; name = name.split( "." )[ 1 ];
fullName = namespace + "-" + name; fullName = namespace + "-" + name;
if ( !prototype ) { if ( !prototype ) {
prototype = base; prototype = base;
base = $.Widget; base = $.Widget;
} }
// create selector for plugin // create selector for plugin
$.expr[ ":" ][ fullName ] = function( elem ) { $.expr[ ":" ][ fullName ] = function( elem ) {
return !!$.data( elem, name ); return !!$.data( elem, name );
}; };
$[ namespace ] = $[ namespace ] || {}; $[ namespace ] = $[ namespace ] || {};
$[ namespace ][ name ] = function( options, element ) { $[ namespace ][ name ] = function( options, element ) {
// allow instantiation without initializing for simple inheritance // allow instantiation without initializing for simple inheritance
if ( arguments.length ) { if ( arguments.length ) {
this._createWidget( options, element ); this._createWidget( options, element );
} }
}; };
var basePrototype = new base(); var basePrototype = new base();
// we need to make the options hash a property directly on the new instance // we need to make the options hash a property directly on the new instance
// otherwise we'll modify the options hash on the prototype that we're // otherwise we'll modify the options hash on the prototype that we're
// inheriting from // inheriting from
// $.each( basePrototype, function( key, val ) { // $.each( basePrototype, function( key, val ) {
// if ( $.isPlainObject(val) ) { // if ( $.isPlainObject(val) ) {
// basePrototype[ key ] = $.extend( {}, val ); // basePrototype[ key ] = $.extend( {}, val );
// } // }
// }); // });
basePrototype.options = $.extend( true, {}, basePrototype.options ); basePrototype.options = $.extend( true, {}, basePrototype.options );
$[ namespace ][ name ].prototype = $.extend( true, basePrototype, { $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
namespace: namespace, namespace: namespace,
widgetName: name, widgetName: name,
widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
widgetBaseClass: fullName widgetBaseClass: fullName
}, prototype ); }, prototype );
$.widget.bridge( name, $[ namespace ][ name ] ); $.widget.bridge( name, $[ namespace ][ name ] );
}; };
$.widget.bridge = function( name, object ) { $.widget.bridge = function( name, object ) {
$.fn[ name ] = function( options ) { $.fn[ name ] = function( options ) {
var isMethodCall = typeof options === "string", var isMethodCall = typeof options === "string",
args = Array.prototype.slice.call( arguments, 1 ), args = Array.prototype.slice.call( arguments, 1 ),
returnValue = this; returnValue = this;
// allow multiple hashes to be passed on init // allow multiple hashes to be passed on init
options = !isMethodCall && args.length ? options = !isMethodCall && args.length ?
$.extend.apply( null, [ true, options ].concat(args) ) : $.extend.apply( null, [ true, options ].concat(args) ) :
options; options;
// prevent calls to internal methods // prevent calls to internal methods
if ( isMethodCall && options.charAt( 0 ) === "_" ) { if ( isMethodCall && options.charAt( 0 ) === "_" ) {
return returnValue; return returnValue;
} }
if ( isMethodCall ) { if ( isMethodCall ) {
this.each(function() { this.each(function() {
var instance = $.data( this, name ), var instance = $.data( this, name ),
methodValue = instance && $.isFunction( instance[options] ) ? methodValue = instance && $.isFunction( instance[options] ) ?
instance[ options ].apply( instance, args ) : instance[ options ].apply( instance, args ) :
instance; instance;
// TODO: add this back in 1.9 and use $.error() (see #5972) // TODO: add this back in 1.9 and use $.error() (see #5972)
// if ( !instance ) { // if ( !instance ) {
// throw "cannot call methods on " + name + " prior to initialization; " + // throw "cannot call methods on " + name + " prior to initialization; " +
// "attempted to call method '" + options + "'"; // "attempted to call method '" + options + "'";
// } // }
// if ( !$.isFunction( instance[options] ) ) { // if ( !$.isFunction( instance[options] ) ) {
// throw "no such method '" + options + "' for " + name + " widget instance"; // throw "no such method '" + options + "' for " + name + " widget instance";
// } // }
// var methodValue = instance[ options ].apply( instance, args ); // var methodValue = instance[ options ].apply( instance, args );
if ( methodValue !== instance && methodValue !== undefined ) { if ( methodValue !== instance && methodValue !== undefined ) {
returnValue = methodValue; returnValue = methodValue;
return false; return false;
} }
}); });
} else { } else {
this.each(function() { this.each(function() {
var instance = $.data( this, name ); var instance = $.data( this, name );
if ( instance ) { if ( instance ) {
instance.option( options || {} )._init(); instance.option( options || {} )._init();
} else { } else {
$.data( this, name, new object( options, this ) ); $.data( this, name, new object( options, this ) );
} }
}); });
} }
return returnValue; return returnValue;
}; };
}; };
$.Widget = function( options, element ) { $.Widget = function( options, element ) {
// allow instantiation without initializing for simple inheritance // allow instantiation without initializing for simple inheritance
if ( arguments.length ) { if ( arguments.length ) {
this._createWidget( options, element ); this._createWidget( options, element );
} }
}; };
$.Widget.prototype = { $.Widget.prototype = {
widgetName: "widget", widgetName: "widget",
widgetEventPrefix: "", widgetEventPrefix: "",
options: { options: {
disabled: false disabled: false
}, },
_createWidget: function( options, element ) { _createWidget: function( options, element ) {
// $.widget.bridge stores the plugin instance, but we do it anyway // $.widget.bridge stores the plugin instance, but we do it anyway
// so that it's stored even before the _create function runs // so that it's stored even before the _create function runs
$.data( element, this.widgetName, this ); $.data( element, this.widgetName, this );
this.element = $( element ); this.element = $( element );
this.options = $.extend( true, {}, this.options = $.extend( true, {},
this.options, this.options,
this._getCreateOptions(), this._getCreateOptions(),
options ); options );
var self = this; var self = this;
this.element.bind( "remove." + this.widgetName, function() { this.element.bind( "remove." + this.widgetName, function() {
self.destroy(); self.destroy();
}); });
this._create(); this._create();
this._trigger( "create" ); this._trigger( "create" );
this._init(); this._init();
}, },
_getCreateOptions: function() { _getCreateOptions: function() {
return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ]; return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
}, },
_create: function() {}, _create: function() {},
_init: function() {}, _init: function() {},
destroy: function() { destroy: function() {
this.element this.element
.unbind( "." + this.widgetName ) .unbind( "." + this.widgetName )
.removeData( this.widgetName ); .removeData( this.widgetName );
this.widget() this.widget()
.unbind( "." + this.widgetName ) .unbind( "." + this.widgetName )
.removeAttr( "aria-disabled" ) .removeAttr( "aria-disabled" )
.removeClass( .removeClass(
this.widgetBaseClass + "-disabled " + this.widgetBaseClass + "-disabled " +
"ui-state-disabled" ); "ui-state-disabled" );
}, },
widget: function() { widget: function() {
return this.element; return this.element;
}, },
option: function( key, value ) { option: function( key, value ) {
var options = key; var options = key;
if ( arguments.length === 0 ) { if ( arguments.length === 0 ) {
// don't return a reference to the internal hash // don't return a reference to the internal hash
return $.extend( {}, this.options ); return $.extend( {}, this.options );
} }
if (typeof key === "string" ) { if (typeof key === "string" ) {
if ( value === undefined ) { if ( value === undefined ) {
return this.options[ key ]; return this.options[ key ];
} }
options = {}; options = {};
options[ key ] = value; options[ key ] = value;
} }
this._setOptions( options ); this._setOptions( options );
return this; return this;
}, },
_setOptions: function( options ) { _setOptions: function( options ) {
var self = this; var self = this;
$.each( options, function( key, value ) { $.each( options, function( key, value ) {
self._setOption( key, value ); self._setOption( key, value );
}); });
return this; return this;
}, },
_setOption: function( key, value ) { _setOption: function( key, value ) {
this.options[ key ] = value; this.options[ key ] = value;
if ( key === "disabled" ) { if ( key === "disabled" ) {
this.widget() this.widget()
[ value ? "addClass" : "removeClass"]( [ value ? "addClass" : "removeClass"](
this.widgetBaseClass + "-disabled" + " " + this.widgetBaseClass + "-disabled" + " " +
"ui-state-disabled" ) "ui-state-disabled" )
.attr( "aria-disabled", value ); .attr( "aria-disabled", value );
} }
return this; return this;
}, },
enable: function() { enable: function() {
return this._setOption( "disabled", false ); return this._setOption( "disabled", false );
}, },
disable: function() { disable: function() {
return this._setOption( "disabled", true ); return this._setOption( "disabled", true );
}, },
_trigger: function( type, event, data ) { _trigger: function( type, event, data ) {
var callback = this.options[ type ]; var callback = this.options[ type ];
event = $.Event( event ); event = $.Event( event );
event.type = ( type === this.widgetEventPrefix ? event.type = ( type === this.widgetEventPrefix ?
type : type :
this.widgetEventPrefix + type ).toLowerCase(); this.widgetEventPrefix + type ).toLowerCase();
data = data || {}; data = data || {};
// copy original event properties over to the new event // copy original event properties over to the new event
// this would happen if we could call $.event.fix instead of $.Event // this would happen if we could call $.event.fix instead of $.Event
// but we don't have a way to force an event to be fixed multiple times // but we don't have a way to force an event to be fixed multiple times
if ( event.originalEvent ) { if ( event.originalEvent ) {
for ( var i = $.event.props.length, prop; i; ) { for ( var i = $.event.props.length, prop; i; ) {
prop = $.event.props[ --i ]; prop = $.event.props[ --i ];
event[ prop ] = event.originalEvent[ prop ]; event[ prop ] = event.originalEvent[ prop ];
} }
} }
this.element.trigger( event, data ); this.element.trigger( event, data );
return !( $.isFunction(callback) && return !( $.isFunction(callback) &&
callback.call( this.element[0], event, data ) === false || callback.call( this.element[0], event, data ) === false ||
event.isDefaultPrevented() ); event.isDefaultPrevented() );
} }
}; };
})( jQuery ); })( jQuery );

View File

@ -1,9 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<title>AdminSortable Test Project</title> <title>AdminSortable Test Project</title>
</head> </head>
<body> <body>
</body> </body>
</html> </html>

32
sample_project/urls.py 100644 → 100755
View File

@ -1,16 +1,16 @@
from django.conf import settings from django.conf import settings
from django.conf.urls.defaults import patterns, url, include from django.conf.urls.defaults import patterns, url, include
from django.contrib import admin from django.contrib import admin
admin.autodiscover() admin.autodiscover()
urlpatterns = patterns('', urlpatterns = patterns('',
(r'^admin/doc/', include('django.contrib.admindocs.urls')), (r'^admin/doc/', include('django.contrib.admindocs.urls')),
(r'^admin/', include(admin.site.urls)), (r'^admin/', include(admin.site.urls)),
) )
if settings.SERVE_STATIC_MEDIA: if settings.SERVE_STATIC_MEDIA:
urlpatterns += patterns('', urlpatterns += patterns('',
(r'^' + settings.MEDIA_URL.lstrip('/'), include('appmedia.urls')), (r'^' + settings.MEDIA_URL.lstrip('/'), include('appmedia.urls')),
) + urlpatterns ) + urlpatterns

56
setup.py 100644 → 100755
View File

@ -1,28 +1,28 @@
from setuptools import setup, find_packages from setuptools import setup, find_packages
try: try:
README = open('README').read() README = open('README').read()
except: except:
README = None README = None
setup( setup(
name='django-admin-sortable', name='django-admin-sortable',
version=__import__('adminsortable').__version__, version=__import__('adminsortable').__version__,
description='Drag and drop sorting for models and inline models in Django admin', description='Drag and drop sorting for models and inline models in Django admin',
long_description=README, long_description=README,
license='APL', license='APL',
author='Brandon Taylor', author='Brandon Taylor',
author_email='btaylorweb@gmail.com', author_email='btaylorweb@gmail.com',
url='http://btaylorweb.com/', url='http://btaylorweb.com/',
packages=find_packages(exclude=['sample_project']), packages=find_packages(exclude=['sample_project']),
zip_safe=False, zip_safe=False,
include_package_data=True, include_package_data=True,
classifiers=['Development Status :: 4 - Beta', classifiers=['Development Status :: 4 - Beta',
'Environment :: Web Environment', 'Environment :: Web Environment',
'Framework :: Django', 'Framework :: Django',
'Intended Audience :: Developers', 'Intended Audience :: Developers',
'License :: OSI Approved :: Apache Software License', 'License :: OSI Approved :: Apache Software License',
'Operating System :: OS Independent', 'Operating System :: OS Independent',
'Programming Language :: Python', 'Programming Language :: Python',
'Topic :: Utilities'], 'Topic :: Utilities'],
) )