Making sure everything is in the repo

This commit is contained in:
Corey Oordt 2009-07-07 07:06:36 -04:00
parent 94a0a41443
commit 8d48c8c042
41 changed files with 2182 additions and 108 deletions

View file

@ -1,99 +1,48 @@
from ellington.categories.models import Hierarchy, Category, Alias
from models import Category
from django.contrib import admin
from django import forms
from ellington.core.forms import RequiredModelForm
from django.template.defaultfilters import slugify
from mptt.forms import TreeNodeChoiceField
from editor import TreeEditorMixin
class CategoryAdminForm(RequiredModelForm):
required_if_other_not_given = {
'hierarchy': 'parent',
'parent': 'hierarchy',
}
class CategoryAdminForm(forms.ModelForm):
parent = TreeNodeChoiceField(queryset=Category.tree.all(), level_indicator=u'+-', required=False)
class Meta:
model = Category
def clean_name(self):
if '/' in self.cleaned_data['name']:
raise forms.ValidationError, "A category name can't contain slashes."
return self.cleaned_data['name']
def clean_slug(self):
self.cleaned_data['slug'] = slugify(self.cleaned_data['name'])
return self.cleaned_data['slug']
def clean(self):
super(CategoryAdminForm, self).clean()
if 'slug' in self.cleaned_data and 'parent' in self.cleaned_data and 'hierarchy' in self.cleaned_data:
if self.cleaned_data['parent'] is not None:
# inherit from parent
self.cleaned_data['hierarchy'] = self.cleaned_data['parent'].hierarchy
#Validate slug
kwargs = {}
if self.cleaned_data.get('hierarchy', False):
kwargs['hierarchy__pk'] = int(self.cleaned_data['hierarchy'].id)
kwargs['parent__isnull'] = True
else:
kwargs['parent__pk'] = int(self.cleaned_data['parent'].id)
this_level_slugs = [c.slug for c in Category.objects.filter(**kwargs) if c.id != self.cleaned_data.get("id", None)]
if self.cleaned_data['slug'] in this_level_slugs:
raise forms.ValidationError("A category slug must be unique among categories at its level.")
#Validate Category Parent
"Makes sure the category doesn't set itself or any of its children as its parent."
if not self.cleaned_data['parent']:
return self.cleaned_data
p_data = int(self.cleaned_data['parent'].pk)
h_data = self.cleaned_data.get('hierarchy', False)
if h_data:
h_data = int(h_data.pk)
if p_data and h_data:
p = Category.objects.get(pk=p_data)
if p.hierarchy_id != h_data:
raise forms.ValidationError("This parent is not within the selected hierarchy.")
# Check that the parent isn't a child of this category
# Requires that we look up "this" object; if it doesn't exist
# we can assume we're at the add stage and return
this_id = self.cleaned_data.get("id", None)
if not this_id:
return self.cleaned_data
try:
selected_parent = Category.objects.get(pk=p_data)
except Category.DoesNotExist:
return self.cleaned_data
if selected_parent.id == this_id:
raise forms.ValidationError("A category can't be its own parent.")
try:
this_category = Category.objects.get(pk=p_data)
except Category.DoesNotExist:
return self.cleaned_data
for c in this_category.get_all_children():
if c.id == this_id:
raise forms.ValidationError("A category can't set a child category to be its own parent.")
return self.cleaned_data
# Validate slug is valid in that level
kwargs = {}
if self.cleaned_data.get('parent', None) is None:
kwargs['parent__isnull'] = True
else:
raise forms.ValidationError("Cannot clean data")
kwargs['parent__pk'] = int(self.cleaned_data['parent'].id)
this_level_slugs = [c['slug'] for c in Category.objects.filter(**kwargs).values('id','slug') if c['id'] != self.instance.id]
if self.cleaned_data['slug'] in this_level_slugs:
raise forms.ValidationError("A category slug must be unique among categories at its level.")
# Validate Category Parent
# Make sure the category doesn't set itself or any of its children as its parent."
if self.cleaned_data.get('parent', None) is None or self.instance.id is None:
return self.cleaned_data
elif self.cleaned_data['parent'].id == self.instance.id:
raise forms.ValidationError("You can't set the parent of the category to itself.")
elif self.cleaned_data['parent'].id in [i[0] for i in self.instance.get_descendants().values_list('id')]:
raise forms.ValidationError("You can't set the parent of the category to a descendant.")
return self.cleaned_data
class CategoryAdmin(admin.ModelAdmin):
class CategoryAdmin(TreeEditorMixin, admin.ModelAdmin):
form=CategoryAdminForm
fields = ('hierarchy', 'parent', 'name', 'slug')
list_display = ('__unicode__',)
list_filter = ('hierarchy',)
search_fields = ('name', 'path')
search_fields = (('name',))
prepopulated_fields = {'slug': ('name',)}
class HierarchyAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('name',)}
class AliasAdmin(admin.ModelAdmin):
list_display = ['category', 'parent']
search_fields = ['category__name', 'parent__name']
admin.site.register(Category, CategoryAdmin)
admin.site.register(Hierarchy, HierarchyAdmin)
admin.site.register(Alias, AliasAdmin)

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

View file

@ -0,0 +1,54 @@
#popup_container {
font-family: Arial, sans-serif;
font-size: 12px;
min-width: 300px; /* Dialog will be no smaller than this */
max-width: 600px; /* Dialog will wrap after this width */
background: #FFF;
border: solid 1px #666;
color: #000;
}
#popup_title {
font-size: 14px;
font-weight: bold;
text-align: center;
line-height: 1.75em;
color: #666;
background: #eee url(images/title.gif) top repeat-x;
border: solid 1px #FFF;
border-bottom: solid 1px #666;
cursor: default;
padding: 0em;
margin: 0em;
}
#popup_content {
background: 16px 16px no-repeat url(../img/info.gif);
padding: 1em 1.75em;
margin: 0em;
}
#popup_content.alert {
background-image: url(../img/info.gif);
}
#popup_content.confirm {
background-image: url(../img/important.gif);
}
#popup_content.prompt {
background-image: url(../img/help.gif);
}
#popup_message {
padding-left: 48px;
}
#popup_panel {
text-align: center;
margin: 1em 0em 0em 1em;
}
#popup_prompt {
margin: .5em 0em;
}

View file

@ -0,0 +1,47 @@
/* jQuery TreeTable Core 2.0 stylesheet
*
* This file contains styles that are used to display the tree table. Each tree
* table is assigned the +treeTable+ class.
* ========================================================================= */
/* jquery.treeTable.collapsible
* ------------------------------------------------------------------------- */
.treeTable tr td .expander {
background-position: left center;
background-repeat: no-repeat;
cursor: pointer;
padding: 0;
zoom: 1; /* IE7 Hack */
}
.treeTable tr.collapsed td .expander {
background-image: url(../img/toggle-expand-dark.png);
}
.treeTable tr.expanded td .expander {
background-image: url(../img/toggle-collapse-dark.png);
}
/* jquery.treeTable.sortable
* ------------------------------------------------------------------------- */
.treeTable tr.selected, .treeTable tr.accept {
/*background-color: #7799ff;
color: #fff;*/
}
.treeTable tr.append {
border-bottom: 2px solid #7799ff;
}
.treeTable tr.collapsed.selected td .expander, .treeTable tr.collapsed.accept td .expander {
/*background-image: url(../img/toggle-expand-light.png);*/
}
.treeTable tr.expanded.selected td .expander, .treeTable tr.expanded.accept td .expander {
/*background-image: url(../img/toggle-collapse-light.png);*/
}
.treeTable .ui-draggable-dragging {
color: #000;
z-index: 1;
}

View file

@ -0,0 +1,217 @@
#content.colM {
width:745px;
}
.navi_tab {
float:left;
padding: 3px 10px 3px 10px;
cursor:pointer;
border: 1px solid #ccc;
border-bottom:none;
min-width:100px;
margin-top:3px;
height:13px;
font-weight: normal;
background-image:none;
color: black;
}
.tab_active {
margin-top: 0;
height:16px;
font-weight: bold;
background-image:url('../img/default-bg.gif');
color: white;
}
#main {
clear:both;
padding: 10px 10px 10px 10px;
border: 1px solid #ccc;
margin: 0 0 10px 0;
}
.panel {
display:none;
position:relative;
padding-bottom:50px;
}
.order-machine {
margin-bottom:10px;
}
.order-item {
margin: 0 0 10px 0;
position:relative;
}
.order-item .handle {
display: block;
height: 100%;
width: 650px;
cursor: move;
}
.item-delete {
cursor:pointer;
float:right;
margin:3px 0px 0px 5px;
}
.active-item {
background-color:#eee;
}
.highlight {
height: 26px;
background-color:#def;
margin: 0 0 10px 0;
}
.button {
margin:5px; padding:5px;
font-weight: bold;
background-image:url('../img/nav-bg.gif');
cursor:pointer;
border: 1px solid #678;
width:30px;
}
th { vertical-align: middle; }
#test-log { padding: 5px; border: 1px solid #ccc; }
#overview span { margin-right:15px; margin-left:5px;}
.richtextcontent {display:none;}
select {
max-width: 580px;
}
textarea {
width: 580px;
margin-top:5px;
margin-bottom:5px;
}
.item-minimize {
width: 15px;
height:15px;
float: left;
cursor: pointer;
margin-left:-17px;
}
.item-minimize-disabled {
width: 15px;
height:15px;
float: left;
margin-left:-17px;
}
.machine-control {
height:50px;
padding: 5px 0px 5px 0px;
border: 1px solid #ccc;
background-color:#fff;
width:743px;
position:absolute;
left:-11px;
bottom:-11px;
}
.control-unit {
float:left;
padding-left:15px;
padding-right:10px;
border-right: 1px solid #eee;
}
.control-unit span {
font-weight:bold;
}
.empty-machine-msg {
margin:10px 0px 5px 300px;
font-style: italic;
font-size:14px;
color:#999;
}
td span select {
width:600px;
}
.popup_bg {
width:100%; height:100%;
background-color:white;
opacity: 0.5;
filter:alpha(opacity=50);
position:absolute;
top:0px; left:0px;
}
#sitetree-wrapper {
margin: 0;
padding: 20px 1px 0 1px;
}
#sitetree {
width: 100%;
}
#sitetree tr td {
overflow: hidden;
white-space: nowrap;
}
.title-col {
position:relative;
z-index:2;
background-color:none;
}
td div.wrap {
border: 0px solid #000;
margin: -5px;
padding: 4px;
position:relative;
}
.insert-as-child {
position:absolute;
bottom:-3px;
left: 15px;
height:15px;
width:100%;
border: 0px solid #0f0;
}
.insert-as-sibling {
position:absolute;
top:0px;
left: 15px;
height:10px;
width:100%;
border: 0px solid #f00;
}
.nohover {
background-color: #eef;
}
.flash {
background-color: #afa;
}
.hover-as-child {
background-color:#cdf;
}
.hover-as-sibling {
border: 1px solid #aee;
}
.move-node {
cursor: move;
margin-left:5px;
}
.del-page {
cursor: pointer;
}

View file

@ -0,0 +1,85 @@
function region_append(region, obj, modname) {
var wrp = [];
wrp.push('<fieldset class="module aligned order-item">');
wrp.push('<h2><img class="item-delete" src="'+IMG_DELETELINK_PATH+'" /><span class="handle">'+modname+'</span></h2>');
wrp.push('<div class="item-content"></div>');
wrp.push('</fieldset>');
$("#"+REGIONS[region]+"_body").children("div.order-machine").append(wrp.join(""))
.children("fieldset.order-item:last").children(".item-content").append(obj);
}
function create_new_spare_form(form, modvar, last_id) {
// create new spare form
var new_form = form.html().replace(
new RegExp(modvar+'-'+last_id, 'g'),
modvar+'-'+(last_id+1));
new_form = '<div id="'+modvar+'_set_item_'+(last_id+1)+'">'+new_form+'</div>';
$("#"+modvar+"_set").append(new_form);
}
function set_item_field_value(item, field, value) {
// item: DOM object created by 'region_append' function
// field: "order-field" | "delete-field" | "region-choice-field"
if (field=="delete-field")
item.find("."+field).attr("checked",value);
else if (field=="region-choice-field") {
var old_region_id = REGION_MAP.indexOf(item.find("."+field).val());
item.find("."+field).val(REGION_MAP[value]);
old_region_item = $("#"+REGIONS[old_region_id]+"_body");
if (old_region_item.children("div.order-machine").children().length == 0)
old_region_item.children("div.empty-machine-msg").show();
else
old_region_item.children("div.empty-machine-msg").hide();
new_region_item = $("#"+REGIONS[value]+"_body");
new_region_item.children("div.empty-machine-msg").hide();
}
else
item.find("."+field).val(value);
}
function move_item (region_id, item) {
poorify_rich(item);
$("#"+REGIONS[region_id]+"_body").children("div.order-machine").append(item);
set_item_field_value(item, "region-choice-field", region_id);
richify_poor(item);
}
function poorify_rich(item){
item.children(".item-content").hide();
if (item.find("div[id^=richtext]").length > 0) {
var editor_id = item.find(".mceEditor").prev().attr("id");
tinyMCE.execCommand('mceRemoveControl', false, editor_id);
}
}
function richify_poor(item){
item.children(".item-content").show();
if (item.find("div[id^=richtext]").length > 0) {
var editor_id = item.find('textarea[name*=richtext]:visible').attr("id");
tinyMCE.execCommand('mceAddControl', false, editor_id);
}
}
function zucht_und_ordnung(move_item) {
for (var i=0; i<REGIONS.length;i++) {
var container = $("#"+REGIONS[i]+"_body div.order-machine");
for (var j=0; j<container.children().length; j++) {
if (move_item)
container.find("input.order-field[value="+j+"]").parents("fieldset.order-item").appendTo(container);
else
set_item_field_value(container.find("fieldset.order-item:eq("+j+")"), "order-field", j);
}
}
}
function attach_dragdrop_handlers() {
// hide content on drag n drop
$("#main h2.handle").mousedown(function(){
poorify_rich($(this).parents("fieldset.order-item"));
});
$("#main h2.handle").mouseup(function(){
richify_poor($(this).parents("fieldset.order-item"));
});
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 536 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 620 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,54 @@
#popup_container {
font-family: Arial, sans-serif;
font-size: 12px;
min-width: 300px; /* Dialog will be no smaller than this */
max-width: 600px; /* Dialog will wrap after this width */
background: #FFF;
border: solid 1px #666;
color: #000;
}
#popup_title {
font-size: 14px;
font-weight: bold;
text-align: center;
line-height: 1.75em;
color: #666;
background: #eee url(img/title.gif) top repeat-x;
border: solid 1px #FFF;
border-bottom: solid 1px #666;
cursor: default;
padding: 0em;
margin: 0em;
}
#popup_content {
background: 16px 16px no-repeat url(img/info.gif);
padding: 1em 1.75em;
margin: 0em;
}
#popup_content.alert {
background-image: url(img/info.gif);
}
#popup_content.confirm {
background-image: url(img/important.gif);
}
#popup_content.prompt {
background-image: url(img/help.gif);
}
#popup_message {
padding-left: 48px;
}
#popup_panel {
text-align: center;
margin: 1em 0em 0em 1em;
}
#popup_prompt {
margin: .5em 0em;
}

View file

@ -0,0 +1,235 @@
// jQuery Alert Dialogs Plugin
//
// Version 1.0
//
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
// 29 December 2008
//
// Visit http://abeautifulsite.net/notebook/87 for more information
//
// Usage:
// jAlert( message, [title, callback] )
// jConfirm( message, [title, callback] )
// jPrompt( message, [value, title, callback] )
//
// History:
//
// 1.00 - Released (29 December 2008)
//
// License:
//
// This plugin is licensed under the GNU General Public License: http://www.gnu.org/licenses/gpl.html
//
(function($) {
$.alerts = {
// These properties can be read/written by accessing $.alerts.propertyName from your scripts at any time
verticalOffset: -75, // vertical offset of the dialog from center screen, in pixels
horizontalOffset: 0, // horizontal offset of the dialog from center screen, in pixels/
repositionOnResize: true, // re-centers the dialog on window resize
overlayOpacity: .01, // transparency level of overlay
overlayColor: '#FFF', // base color of overlay
draggable: true, // make the dialogs draggable (requires UI Draggables plugin)
okButton: '&nbsp;OK&nbsp;', // text for the OK button
cancelButton: '&nbsp;Cancel&nbsp;', // text for the Cancel button
dialogClass: null, // if specified, this class will be applied to all dialogs
// Public methods
alert: function(message, title, callback) {
if( title == null ) title = 'Alert';
$.alerts._show(title, message, null, 'alert', function(result) {
if( callback ) callback(result);
});
},
confirm: function(message, title, callback) {
if( title == null ) title = 'Confirm';
$.alerts._show(title, message, null, 'confirm', function(result) {
if( callback ) callback(result);
});
},
prompt: function(message, value, title, callback) {
if( title == null ) title = 'Prompt';
$.alerts._show(title, message, value, 'prompt', function(result) {
if( callback ) callback(result);
});
},
// Private methods
_show: function(title, msg, value, type, callback) {
$.alerts._hide();
$.alerts._overlay('show');
$("BODY").append(
'<div id="popup_container">' +
'<h1 id="popup_title"></h1>' +
'<div id="popup_content">' +
'<div id="popup_message"></div>' +
'</div>' +
'</div>');
if( $.alerts.dialogClass ) $("#popup_container").addClass($.alerts.dialogClass);
// IE6 Fix
var pos = ($.browser.msie && parseInt($.browser.version) <= 6 ) ? 'absolute' : 'fixed';
$("#popup_container").css({
position: pos,
zIndex: 99999,
padding: 0,
margin: 0
});
$("#popup_title").text(title);
$("#popup_content").addClass(type);
$("#popup_message").text(msg);
$("#popup_message").html( $("#popup_message").text().replace(/\n/g, '<br />') );
$("#popup_container").css({
minWidth: $("#popup_container").outerWidth(),
maxWidth: $("#popup_container").outerWidth()
});
$.alerts._reposition();
$.alerts._maintainPosition(true);
switch( type ) {
case 'alert':
$("#popup_message").after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" /></div>');
$("#popup_ok").click( function() {
$.alerts._hide();
callback(true);
});
$("#popup_ok").focus().keypress( function(e) {
if( e.keyCode == 13 || e.keyCode == 27 ) $("#popup_ok").trigger('click');
});
break;
case 'confirm':
$("#popup_message").after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" /> <input type="button" value="' + $.alerts.cancelButton + '" id="popup_cancel" /></div>');
$("#popup_ok").click( function() {
$.alerts._hide();
if( callback ) callback(true);
});
$("#popup_cancel").click( function() {
$.alerts._hide();
if( callback ) callback(false);
});
$("#popup_ok").focus();
$("#popup_ok, #popup_cancel").keypress( function(e) {
if( e.keyCode == 13 ) $("#popup_ok").trigger('click');
if( e.keyCode == 27 ) $("#popup_cancel").trigger('click');
});
break;
case 'prompt':
$("#popup_message").append('<br /><input type="text" size="30" id="popup_prompt" />').after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" /> <input type="button" value="' + $.alerts.cancelButton + '" id="popup_cancel" /></div>');
$("#popup_prompt").width( $("#popup_message").width() );
$("#popup_ok").click( function() {
var val = $("#popup_prompt").val();
$.alerts._hide();
if( callback ) callback( val );
});
$("#popup_cancel").click( function() {
$.alerts._hide();
if( callback ) callback( null );
});
$("#popup_prompt, #popup_ok, #popup_cancel").keypress( function(e) {
if( e.keyCode == 13 ) $("#popup_ok").trigger('click');
if( e.keyCode == 27 ) $("#popup_cancel").trigger('click');
});
if( value ) $("#popup_prompt").val(value);
$("#popup_prompt").focus().select();
break;
}
// Make draggable
if( $.alerts.draggable ) {
try {
$("#popup_container").draggable({ handle: $("#popup_title") });
$("#popup_title").css({ cursor: 'move' });
} catch(e) { /* requires jQuery UI draggables */ }
}
},
_hide: function() {
$("#popup_container").remove();
$.alerts._overlay('hide');
$.alerts._maintainPosition(false);
},
_overlay: function(status) {
switch( status ) {
case 'show':
$.alerts._overlay('hide');
$("BODY").append('<div id="popup_overlay"></div>');
$("#popup_overlay").css({
position: 'absolute',
zIndex: 99998,
top: '0px',
left: '0px',
width: '100%',
height: $(document).height(),
background: $.alerts.overlayColor,
opacity: $.alerts.overlayOpacity,
display: 'none'
});
break;
case 'hide':
$("#popup_overlay").remove();
break;
}
},
_reposition: function() {
var top = (($(window).height() / 2) - ($("#popup_container").outerHeight() / 2)) + $.alerts.verticalOffset;
var left = (($(window).width() / 2) - ($("#popup_container").outerWidth() / 2)) + $.alerts.horizontalOffset;
if( top < 0 ) top = 0;
if( left < 0 ) left = 0;
// IE6 fix
if( $.browser.msie && parseInt($.browser.version) <= 6 ) top = top + $(window).scrollTop();
$("#popup_container").css({
top: top + 'px',
left: left + 'px'
});
$("#popup_overlay").height( $(document).height() );
},
_maintainPosition: function(status) {
if( $.alerts.repositionOnResize ) {
switch(status) {
case true:
$(window).bind('resize', function() {
$.alerts._reposition();
});
break;
case false:
$(window).unbind('resize');
break;
}
}
}
}
// Shortuct functions
jAlert = function(message, title, callback) {
$.alerts.alert(message, title, callback);
}
jConfirm = function(message, title, callback) {
$.alerts.confirm(message, title, callback);
};
jPrompt = function(message, value, title, callback) {
$.alerts.prompt(message, value, title, callback);
};
})(jQuery);

View file

@ -0,0 +1,156 @@
/*
* jQuery JSON Plugin
* version: 1.0 (2008-04-17)
*
* This document is licensed as free software under the terms of the
* MIT License: http://www.opensource.org/licenses/mit-license.php
*
* Brantley Harris technically wrote this plugin, but it is based somewhat
* on the JSON.org website's http://www.json.org/json2.js, which proclaims:
* "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that
* I uphold. I really just cleaned it up.
*
* It is also based heavily on MochiKit's serializeJSON, which is
* copywrited 2005 by Bob Ippolito.
*/
(function($) {
function toIntegersAtLease(n)
// Format integers to have at least two digits.
{
return n < 10 ? '0' + n : n;
}
Date.prototype.toJSON = function(date)
// Yes, it polutes the Date namespace, but we'll allow it here, as
// it's damned usefull.
{
return this.getUTCFullYear() + '-' +
toIntegersAtLease(this.getUTCMonth()) + '-' +
toIntegersAtLease(this.getUTCDate());
};
var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g;
var meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
};
$.quoteString = function(string)
// Places quotes around a string, inteligently.
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
{
if (escapeable.test(string))
{
return '"' + string.replace(escapeable, function (a)
{
var c = meta[a];
if (typeof c === 'string') {
return c;
}
c = a.charCodeAt();
return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
}) + '"';
}
return '"' + string + '"';
};
$.toJSON = function(o, compact)
{
var type = typeof(o);
if (type == "undefined")
return "undefined";
else if (type == "number" || type == "boolean")
return o + "";
else if (o === null)
return "null";
// Is it a string?
if (type == "string")
{
return $.quoteString(o);
}
// Does it have a .toJSON function?
if (type == "object" && typeof o.toJSON == "function")
return o.toJSON(compact);
// Is it an array?
if (type != "function" && typeof(o.length) == "number")
{
var ret = [];
for (var i = 0; i < o.length; i++) {
ret.push( $.toJSON(o[i], compact) );
}
if (compact)
return "[" + ret.join(",") + "]";
else
return "[" + ret.join(", ") + "]";
}
// If it's a function, we have to warn somebody!
if (type == "function") {
throw new TypeError("Unable to convert object of type 'function' to json.");
}
// It's probably an object, then.
var ret = [];
for (var k in o) {
var name;
type = typeof(k);
if (type == "number")
name = '"' + k + '"';
else if (type == "string")
name = $.quoteString(k);
else
continue; //skip non-string or number keys
var val = $.toJSON(o[k], compact);
if (typeof(val) != "string") {
// skip non-serializable values
continue;
}
if (compact)
ret.push(name + ":" + val);
else
ret.push(name + ": " + val);
}
return "{" + ret.join(", ") + "}";
};
$.compactJSON = function(o)
{
return $.toJSON(o, true);
};
$.evalJSON = function(src)
// Evals JSON that we know to be safe.
{
return eval("(" + src + ")");
};
$.secureEvalJSON = function(src)
// Evals JSON in a way that is *more* secure.
{
var filtered = src;
filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@');
filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
if (/^[\],:{}\s]*$/.test(filtered))
return eval("(" + src + ")");
else
throw new SyntaxError("Error parsing JSON, source is not valid.");
};
})(jQuery);

View file

@ -0,0 +1,250 @@
/*! Copyright (c) 2008 Brandon Aaron (http://brandonaaron.net)
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
*
* Version: 1.0.3
* Requires jQuery 1.1.3+
* Docs: http://docs.jquery.com/Plugins/livequery
*/
(function($) {
$.extend($.fn, {
livequery: function(type, fn, fn2) {
var self = this, q;
// Handle different call patterns
if ($.isFunction(type))
fn2 = fn, fn = type, type = undefined;
// See if Live Query already exists
$.each( $.livequery.queries, function(i, query) {
if ( self.selector == query.selector && self.context == query.context &&
type == query.type && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid) )
// Found the query, exit the each loop
return (q = query) && false;
});
// Create new Live Query if it wasn't found
q = q || new $.livequery(this.selector, this.context, type, fn, fn2);
// Make sure it is running
q.stopped = false;
// Run it immediately for the first time
q.run();
// Contnue the chain
return this;
},
expire: function(type, fn, fn2) {
var self = this;
// Handle different call patterns
if ($.isFunction(type))
fn2 = fn, fn = type, type = undefined;
// Find the Live Query based on arguments and stop it
$.each( $.livequery.queries, function(i, query) {
if ( self.selector == query.selector && self.context == query.context &&
(!type || type == query.type) && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid) && !this.stopped )
$.livequery.stop(query.id);
});
// Continue the chain
return this;
}
});
$.livequery = function(selector, context, type, fn, fn2) {
this.selector = selector;
this.context = context || document;
this.type = type;
this.fn = fn;
this.fn2 = fn2;
this.elements = [];
this.stopped = false;
// The id is the index of the Live Query in $.livequery.queries
this.id = $.livequery.queries.push(this)-1;
// Mark the functions for matching later on
fn.$lqguid = fn.$lqguid || $.livequery.guid++;
if (fn2) fn2.$lqguid = fn2.$lqguid || $.livequery.guid++;
// Return the Live Query
return this;
};
$.livequery.prototype = {
stop: function() {
var query = this;
if ( this.type )
// Unbind all bound events
this.elements.unbind(this.type, this.fn);
else if (this.fn2)
// Call the second function for all matched elements
this.elements.each(function(i, el) {
query.fn2.apply(el);
});
// Clear out matched elements
this.elements = [];
// Stop the Live Query from running until restarted
this.stopped = true;
},
run: function() {
// Short-circuit if stopped
if ( this.stopped ) return;
var query = this;
var oEls = this.elements,
els = $(this.selector, this.context),
nEls = els.not(oEls);
// Set elements to the latest set of matched elements
this.elements = els;
if (this.type) {
// Bind events to newly matched elements
nEls.bind(this.type, this.fn);
// Unbind events to elements no longer matched
if (oEls.length > 0)
$.each(oEls, function(i, el) {
if ( $.inArray(el, els) < 0 )
$.event.remove(el, query.type, query.fn);
});
}
else {
// Call the first function for newly matched elements
nEls.each(function() {
query.fn.apply(this);
});
// Call the second function for elements no longer matched
if ( this.fn2 && oEls.length > 0 )
$.each(oEls, function(i, el) {
if ( $.inArray(el, els) < 0 )
query.fn2.apply(el);
});
}
}
};
$.extend($.livequery, {
guid: 0,
queries: [],
queue: [],
running: false,
timeout: null,
checkQueue: function() {
if ( $.livequery.running && $.livequery.queue.length ) {
var length = $.livequery.queue.length;
// Run each Live Query currently in the queue
while ( length-- )
$.livequery.queries[ $.livequery.queue.shift() ].run();
}
},
pause: function() {
// Don't run anymore Live Queries until restarted
$.livequery.running = false;
},
play: function() {
// Restart Live Queries
$.livequery.running = true;
// Request a run of the Live Queries
$.livequery.run();
},
registerPlugin: function() {
$.each( arguments, function(i,n) {
// Short-circuit if the method doesn't exist
if (!$.fn[n]) return;
// Save a reference to the original method
var old = $.fn[n];
// Create a new method
$.fn[n] = function() {
// Call the original method
var r = old.apply(this, arguments);
// Request a run of the Live Queries
$.livequery.run();
// Return the original methods result
return r;
}
});
},
run: function(id) {
if (id != undefined) {
// Put the particular Live Query in the queue if it doesn't already exist
if ( $.inArray(id, $.livequery.queue) < 0 )
$.livequery.queue.push( id );
}
else
// Put each Live Query in the queue if it doesn't already exist
$.each( $.livequery.queries, function(id) {
if ( $.inArray(id, $.livequery.queue) < 0 )
$.livequery.queue.push( id );
});
// Clear timeout if it already exists
if ($.livequery.timeout) clearTimeout($.livequery.timeout);
// Create a timeout to check the queue and actually run the Live Queries
$.livequery.timeout = setTimeout($.livequery.checkQueue, 20);
},
stop: function(id) {
if (id != undefined)
// Stop are particular Live Query
$.livequery.queries[ id ].stop();
else
// Stop all Live Queries
$.each( $.livequery.queries, function(id) {
$.livequery.queries[ id ].stop();
});
}
});
// Register core DOM manipulation methods
$.livequery.registerPlugin('append', 'prepend', 'after', 'before', 'wrap', 'attr', 'removeAttr', 'addClass', 'removeClass', 'toggleClass', 'empty', 'remove');
// Run Live Queries when the Document is ready
$(function() { $.livequery.play(); });
// Save a reference to the original init method
var init = $.prototype.init;
// Create a new init method that exposes two new properties: selector and context
$.prototype.init = function(a,c) {
// Call the original init and save the result
var r = init.apply(this, arguments);
// Copy over properties if they exist already
if (a && a.selector)
r.context = a.context, r.selector = a.selector;
// Set properties
if ( typeof a == 'string' )
r.context = c || document, r.selector = a;
// Return the result
return r;
};
// Give the init function the jQuery prototype for later instantiation (needed after Rev 4091)
$.prototype.init.prototype = $.prototype;
})(jQuery);

View file

@ -0,0 +1,384 @@
/* jQuery treeTable Plugin 2.2 - http://ludo.cubicphuse.nl/jquery-plugins/treeTable/ */
(function($) {
// Helps to make options available to all functions
// TODO: This gives problems when there are both expandable and non-expandable
// trees on a page. The options shouldn't be global to all these instances!
var options;
$.fn.treeTable = function(opts) {
options = $.extend({}, $.fn.treeTable.defaults, opts);
return this.each(function() {
$(this).addClass("treeTable").find("tbody tr").each(function() {
// Initialize root nodes only whenever possible
if(!options.expandable || $(this)[0].className.search("child-of-") == -1) {
initialize($(this));
}
});
});
};
$.fn.treeTable.defaults = {
childPrefix: "child-of-",
expandable: true,
indent: 19,
initialState: "collapsed",
treeColumn: 0
};
// Recursively hide all node's children in a tree
$.fn.collapse = function() {
$(this).addClass("collapsed");
childrenOf($(this)).each(function() {
initialize($(this));
if(!$(this).hasClass("collapsed")) {
$(this).collapse();
}
$(this).hide();
});
return this;
};
// Recursively show all node's children in a tree
$.fn.expand = function() {
$(this).removeClass("collapsed").addClass("expanded");
childrenOf($(this)).each(function() {
initialize($(this));
if($(this).is(".expanded.parent")) {
$(this).expand();
}
$(this).show();
});
return this;
};
// Add an entire branch to +destination+
$.fn.appendBranchTo = function(destination) {
var node = $(this);
var parent = parentOf(node);
var ancestorNames = $.map(ancestorsOf(destination), function(a) { return a.id; });
// Conditions:
// 1: +node+ should not be inserted in a location in a branch if this would
// result in +node+ being an ancestor of itself.
// 2: +node+ should not have a parent OR the destination should not be the
// same as +node+'s current parent (this last condition prevents +node+
// from being moved to the same location where it already is).
// 3: +node+ should not be inserted as a child of +node+ itself.
if($.inArray(node[0].id, ancestorNames) == -1 && (!parent || (destination.attr("id") != parent[0].id)) && destination.attr("id") != node[0].id) {
indent(node, ancestorsOf(node).length * options.indent * -1); // Remove indentation
if(parent) { node.removeClass(options.childPrefix + parent[0].id); }
var dest_id = $(destination).attr("id");
while ($(".child-of-"+dest_id).length > 0) {
var move_to = $(".child-of-"+dest_id+":last");
dest_id = move_to.attr("id");
}
node.addClass(options.childPrefix + destination.attr("id"));
if (move_to)
moveChild(node, move_to); // Recursively move nodes to new location
else
moveChild(node, destination);
indent(node, ancestorsOf(node).length * options.indent);
}
return this;
};
$.fn.insertBranchBefore = function(destination) {
var node = $(this);
var parent = parentOf_jQuery(node);
var dest_parent = parentOf_jQuery(destination);
if ($(this).attr("id")==destination.attr("id"))
return false;
var ancestorNames = $.map(ancestorsOf_jQuery(destination), function(a) { return a.id; });
indent(node, ancestorsOf_jQuery(node).length * options.indent * -1); // Remove indentation
if(parent) { node.removeClass(options.childPrefix + parent[0].id); }
if (dest_parent)
node.addClass(options.childPrefix + dest_parent.attr("id"));
moveBefore(node, destination); // Recursively move nodes to new location
indent(node, (ancestorsOf_jQuery(node).length * options.indent));
return this;
};
// Add reverse() function from JS Arrays
$.fn.reverse = function() {
return this.pushStack(this.get().reverse(), arguments);
};
// Toggle an entire branch
$.fn.toggleBranch = function() {
if($(this).hasClass("collapsed")) {
$(this).expand();
} else {
$(this).removeClass("expanded").collapse();
}
return this;
};
// === Private functions
function ancestorsOf(node) {
var ancestors = [];
while(node = parentOf(node)) {
ancestors[ancestors.length] = node[0];
}
return ancestors;
};
function childrenOf(node) {
return $("table.treeTable tbody tr." + options.childPrefix + node[0].id);
};
function indent(node, value) {
var cell = $(node.children("td")[options.treeColumn]);
var padding = parseInt(cell.css("padding-left"), 10) + value;
cell.css("padding-left", + padding + "px");
childrenOf(node).each(function() {
indent($(this), value);
});
};
function initialize(node) {
if(!node.hasClass("initialized")) {
node.addClass("initialized");
var childNodes = childrenOf(node);
if(!node.hasClass("parent") && childNodes.length > 0) {
node.addClass("parent");
}
if(node.hasClass("parent")) {
var cell = $(node.children("td")[options.treeColumn]);
var padding = parseInt(cell.css("padding-left"), 10) + options.indent;
childNodes.each(function() {
$($(this).children("td")[options.treeColumn]).css("padding-left", padding + "px");
});
if(options.expandable) {
cell.children(":first").children("span").prepend('<span style="margin-left: -' + (options.indent-15) + 'px; padding-left: ' + (options.indent-5) + 'px;" class="expander"></span>');
//$(cell[0].firstChild).click(function() { node.toggleBranch(); });
// Check for a class set explicitly by the user, otherwise set the default class
if(!(node.hasClass("expanded") || node.hasClass("collapsed"))) {
node.addClass(options.initialState);
}
if(node.hasClass("collapsed")) {
node.collapse();
} else if (node.hasClass("expanded")) {
node.expand();
}
}
} else {
var cell = $(node.children("td")[options.treeColumn]);
cell.children(":first").children("span").prepend('<span style="margin-left: -' + (options.indent-15) + 'px; padding-left: ' + (options.indent-5) + 'px;"></span>');
}
node.children(":first").addClass("padded");
}
};
function move(node, destination) {
node.insertAfter(destination);
childrenOf(node).reverse().each(function() { move($(this), node[0]); });
};
function moveChild(node, destination) {
node.insertAfter(destination)
childrenOf(node).reverse().each(function() { move($(this), node[0]); });
};
function moveBefore(node, destination) {
node.insertBefore(destination)
childrenOf(node).reverse().each(function() { move($(this), node[0]); });
};
function parentOf(node) {
var classNames = node[0].className.split(' ');
for(key in classNames) {
if(classNames[key].match("child-of-")) {
return $("#" + classNames[key].substring(9));
}
}
};
})(jQuery);
// public functions
function handle_drop_event(source, dest, method){
var ancestorNames = $.map(ancestorsOf_jQuery(dest), function(a) { return a.attr("id"); });
if (method=="child")
dest.find(".wrap").removeClass("hover-as-child").addClass("nohover");
else // method == "sibling"
dest.find("div:first").remove();
// do not drop on itself or its own children, if method == "child"
if ( (method == "sibling") || (source.attr("id") != dest.attr("id") && $.inArray(source.attr("id"), ancestorNames) == -1) ) {
var source_child_of = null;
if (source.attr("class").match(/child-of-node-(\d+)/))
source_child_of = source.attr("class").match(/child-of-node-(\d+)/)[0];
var dest_child_of = "child-of-" + dest.attr("id");
if (source_child_of && $("."+source_child_of).length - 1 == 0) {
var parent_id = "#" + source_child_of.substring(9);
$(parent_id).removeClass("parent");
if ($(parent_id).hasClass("expanded"))
$(parent_id).removeClass("expanded").addClass("collapsed");
$(parent_id+" .title-col span").removeClass("expander");
}
if (method=="child") {
if ($("."+dest_child_of).length == 0) {
var parent_id = "#" + dest_child_of.substring(9);
$(parent_id).addClass("parent").find(".title-col span").addClass("expander");
}
if (!dest.hasClass("expanded"))
dest.expand();
// *** INSERT ***
source.appendBranchTo(dest);
} else // method == "sibling"
source.insertBranchBefore(dest);
}
source.find(".wrap").switchClass("nohover","flash",0).switchClass("flash","nohover",500);
}
function handle_page_delete(node) {
var item_id = node.attr("class").match(/item-id-(\d+)/)[1];
var parent_id = null;
if (node.attr("class").match(/child-of-node-(\d+)/))
parent_id = node.attr("class").match(/child-of-node-(\d+)/)[1];
var popup_bg = '<div class="popup_bg"></div>';
$("body").append(popup_bg);
if (node.hasClass("parent")){
jAlert(DELETE_MESSAGES[4], DELETE_MESSAGES[3], function(){
$(".popup_bg").remove();
});
} else {
jConfirm(DELETE_MESSAGES[0], DELETE_MESSAGES[1], function(r) {
if (r==true) {
$.post('.', {'__cmd': 'delete_item', 'item_id': item_id}, function(data){
if (data == "OK") {
if (parent_id && $(".child-of-node-"+parent_id).length == 1) {
$("#node-"+parent_id).removeClass("parent")
.removeClass("expanded").addClass("collapsed")
.find(".expander").removeClass("expander");
}
node.remove();
$("body").append(popup_bg);
jAlert(DELETE_MESSAGES[2], DELETE_MESSAGES[2], function(){
$(".popup_bg").remove();
});
}
});
}
$(".popup_bg").remove();
});
}
}
function parentOf_jQuery(node) {
if (node.attr("class").match(/child-of-node-(\d+)/)) {
var parent_id = node.attr("class").match(/child-of-node-(\d+)/)[1];
return $("#node-"+parent_id);
}
return null;
};
function ancestorsOf_jQuery(node) {
var ancestors = [];
while(node = parentOf_jQuery(node)) {
ancestors[ancestors.length] = node;
}
return ancestors;
};
function save_page_tree() {
var send_tree = new Array();
// prepare tree
var i = 0;
var ancestor_tree_ids = [];
var ancestor_indices = [];
var tree_id = 0;
$("#sitetree tbody tr").each(function(){
// 0 = tree_id, 1 = parent_id, 2 = left, 3 = right, 4 = level, 5 = item_id
var classNames = $(this).attr("class").split(' ');
var is_child = false;
var is_parent = false;
var parent_id = null;
var item_id = "";
var left = "";
var right = "";
var level = "";
// gather information
for (key in classNames) {
if(classNames[key].match("item-id-"))
item_id = parseInt(classNames[key].substring(8));
if(classNames[key].match("parent"))
is_parent = true;
if(classNames[key].match("child-of-")) {
is_child = true;
var node_parent_id = classNames[key].substring(9);
parent_id = parseInt($("#"+node_parent_id).attr("class").match(/item-id-(\d+)/)[1])
}
}
// save info
var inArray = ancestor_tree_ids.indexOf(parent_id);
while ( ( is_child && inArray < ancestor_tree_ids.length - 1 && inArray >= 0) || ( !is_child && ancestor_tree_ids.length > 0 ) ) {
send_tree[ancestor_indices.pop()][3] = i++;
ancestor_tree_ids.pop();
}
if (!is_child) {
tree_id++;
i = 0;
}
left = i++;
level = ancestor_tree_ids.length;
if (is_parent) {
ancestor_tree_ids.push(item_id);
ancestor_indices.push(send_tree.length);
} else {
right = i++;
}
send_tree.push([tree_id, parent_id?parent_id:null, left, right, level, item_id]);
});
while (ancestor_tree_ids.length>0) {
send_tree[ancestor_indices.pop()][3] = i++;
ancestor_tree_ids.pop();
}
// send tree to url
$.post('.', {'__cmd': 'save_tree', 'tree': $.toJSON(send_tree)}, function(data){
if (data == "OK") {
var popup_bg = '<div class="popup_bg"></div>';
$("body").append(popup_bg);
jAlert(TREE_SAVED_MESSAGE, TREE_SAVED_MESSAGE, function(){
$(".popup_bg").remove();
});
}
});
}

View file

@ -0,0 +1,87 @@
$(document).ready(function(){
$("#main_wrapper > .navi_tab").click(function(){
var elem = $(this);
$("#main_wrapper > .navi_tab").removeClass("tab_active");
elem.addClass("tab_active");
$("#main > div:visible, #main > fieldset:visible").hide();
var tab_str = elem.attr("id").substr(0, elem.attr("id").length-4);
$('#'+tab_str+'_body').show();
ACTIVE_REGION = REGIONS.indexOf(tab_str);
if (tab_str == "settings")
$(".machine-control").hide();
else
$(".machine-control").show();
// make it possible to open current tab on page reload
window.location.hash = '#tab_'+tab_str;
});
$(".order-machine-add-button").click(function(){
var select = $(this).prev();
var modvar = select.val();
var modname = select.children("option:selected").html();
var total_forms = $('#id_'+modvar+'-TOTAL_FORMS');
var last_id = parseInt(total_forms.val()) - 1;
var form = $("#"+modvar+"_set_item_"+last_id);
// update formset bookkeeping value
total_forms.val(last_id+2);
create_new_spare_form(form, modvar, last_id);
region_append(ACTIVE_REGION, form, modname, modvar);
set_item_field_value(form, "region-choice-field", ACTIVE_REGION);
attach_dragdrop_handlers();
init_contentblocks();
});
$(".order-machine-move-button").click(function(){
var moveTo = $(this).prev().val();
move_item(REGIONS.indexOf(moveTo), $("#main div.order-machine div.active-item"));
});
$(".item-delete").livequery('click',function(){
popup_bg = '<div class="popup_bg"></div>';
$("body").append(popup_bg);
var item = $(this).parents(".order-item");
jConfirm(DELETE_MESSAGES[0], DELETE_MESSAGES[1], function(r) {
if (r==true) {
set_item_field_value(item,"delete-field","checked");
item.fadeOut(200);
}
$(".popup_bg").remove();
});
});
$(".change-template").click(function(){
popup_bg = '<div class="popup_bg"></div>';
$("body").append(popup_bg);
jConfirm(CHANGE_TEMPLATE_MESSAGES[1], CHANGE_TEMPLATE_MESSAGES[0], function(r) {
if (r==true) {
var items = $(".panel").children(".order-machine").children();
move_item(0, items);
$("#overview input.submit_form").click();
} else {
$(".popup_bg").remove();
}
});
});
$("fieldset.order-item").livequery('click',function(){
if($(this).hasClass('active-item')) {
$(this).removeClass('active-item')
} else {
$(".order-item.active-item").removeClass("active-item");
$(this).addClass("active-item");
}
});
$('form').submit(function(){
zucht_und_ordnung(false);
var form = $(this);
form.attr('action', form.attr('action')+window.location.hash);
return true;
});
});

View file

@ -4,37 +4,15 @@ from django.db import models
from django.utils.encoding import force_unicode
import mptt
class CategoryTree(models.Model):
"""
A group of categories that are all related under one tree.
For example: Business, Movie Genre, Music Genre
"""
name = models.CharField(max_length=100)
slug = models.SlugField()
class Meta:
ordering = ('name',)
def __unicode__(self):
return self.name
def get_absolute_url(self):
return reverse("categories_tree", args=[self.slug])
class Category(models.Model):
category_tree = models.ForeignKey(CategoryTree,
blank=False,
null=False
related_name="categories")
parent = models.ForeignKey('self',
blank=True,
null=True,
related_name="children",
help_text="Leave this blank for a top-level category",
help_text="Leave this blank for an Category Tree",
verbose_name='Parent')
name = models.CharField(max_length=100)
order = models.IntegerField(blank=True, null=True)
slug = models.SlugField()
def get_absolute_url(self):
@ -46,10 +24,10 @@ class Category(models.Model):
class Meta:
verbose_name_plural = 'categories'
unique_together = (('parent', 'name'),)
ordering = ('category_tree__name','parent__name','name')
ordering = ('name',)
def __unicode__(self):
ancestors = self.get_ancestors()
return ' > '.join([force_unicode(i.name) for i in ancestors])
return ' > '.join([force_unicode(i.name) for i in ancestors]+[self.name,])
mptt.register(Category, order_insertion_by=['name'])

View file

@ -0,0 +1,8 @@
{% load i18n %}
DELETE_MESSAGES = ["{% trans "Really delete item?" %}", "{% trans "Confirm to delete item" %}",
"{% trans "Item deleted successfully." %}", "{% trans "Cannot delete item" %}",
"{% trans "Cannot delete item, because it is parent of at least one other item." %}"];
TREE_SAVED_MESSAGE = "{% trans "Tree saved successfully." %}";
CHANGE_TEMPLATE_MESSAGES = ["{% trans "Change template" %}",
"{% trans "Really change template? <br/>All content will be moved to main region." %}"];

View file

@ -0,0 +1 @@
<div class="fe_box" id="{{ identifier }}">{{ content|safe }}</div>

View file

@ -0,0 +1,57 @@
{% extends "admin/change_form.html" %}
{% load i18n admin_modify adminmedia %}
{% block extrahead %}{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/forms.css" />
<script type="text/javascript" src="../../../jsi18n/"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>
<script type="text/javascript" src="{{ FEINCMS_ADMIN_MEDIA }}jquery.livequery.js"></script>
<script type="text/javascript" src="{{ FEINCMS_ADMIN_MEDIA }}jquery.alerts.js"></script>
<script type="text/javascript" src="{{ FEINCMS_ADMIN_MEDIA }}helper.js"></script>
<script type="text/javascript" src="{{ FEINCMS_ADMIN_MEDIA }}listener.js"></script>
<script type="text/javascript">
var contentblock_init_handlers = [];
</script>
{% for inc in object.feincms_item_editor_includes.head %}{% include inc %}{% endfor %}
<script type="text/javascript">
{% include "admin/feincms/_messages.html" %}
function init_contentblocks() {
for(var k in contentblock_init_handlers)
contentblock_init_handlers[k]();
}
$(function(){
init_contentblocks();
});
</script>
{% endblock %}
{% block content %}
<div class="content_main" id="frontend_editor">
<form method="post" action=".">
<div>
{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
<table>
{{ form }}
</table>
<div class="submit-row" >
<input type="submit" value="{% trans "Save" %}" class="default" name="_save" />
</div>
</div>
</form>
</div>
{% endblock %}

View file

@ -0,0 +1,12 @@
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="{{ FEINCMS_ADMIN_MEDIA }}jquery.color.js"></script>
<div id="{{ identifier }}-new">
{{ content|safe }}
</div>
<script type="text/javascript">
opener.fe_update_content('{{ identifier }}', $('#{{ identifier }}-new').html());
window.close();
</script>

View file

@ -0,0 +1,252 @@
{% extends "admin/change_form.html" %}
{% load i18n admin_modify adminmedia %}
{% block bodyclass %}{{ opts.app_label }}-{{ opts.object_name.lower }} change-form{% endblock %}
{% block coltype %}{% if ordered_objects %}colMS{% else %}colM{% endif %}{% endblock %}
{% block extrahead %}{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/forms.css" />
<script type="text/javascript" src="../../../jsi18n/"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>
<script type="text/javascript" src="{{ FEINCMS_ADMIN_MEDIA }}jquery.livequery.js"></script>
<script type="text/javascript" src="{{ FEINCMS_ADMIN_MEDIA }}jquery.alerts.js"></script>
<script type="text/javascript" src="{{ FEINCMS_ADMIN_MEDIA }}helper.js"></script>
<script type="text/javascript" src="{{ FEINCMS_ADMIN_MEDIA }}listener.js"></script>
<script type="text/javascript">
var contentblock_init_handlers = [];
</script>
{% for inc in object.feincms_item_editor_includes.head %}{% include inc %}{% endfor %}
<script type="text/javascript">
{% include "admin/feincms/_messages.html" %}
function init_contentblocks() {
for(var k in contentblock_init_handlers)
contentblock_init_handlers[k]();
}
IMG_ARROW_DOWN_PATH = "{{ FEINCMS_ADMIN_MEDIA }}img/arrow_down.gif";
IMG_ARROW_RIGHT_PATH = "{{ FEINCMS_ADMIN_MEDIA }}img/arrow_right.gif";
IMG_CIRCLE_PATH = "{{ FEINCMS_ADMIN_MEDIA }}img/circle.gif";
IMG_DELETELINK_PATH = "{{ FEINCMS_ADMIN_MEDIA }}img/icon_deletelink.gif";
IMG_MOVE_PATH = "{{ FEINCMS_ADMIN_MEDIA }}img/icon_move.gif";
REGIONS = [];
REGION_MAP = [];
{% for region in object.template.regions %}
REGIONS.push('{{ region.key }}');
REGION_MAP.push('{{ region.key }}');
{% endfor %}
ACTIVE_REGION = 0;
CONTENT_NAMES = {
{% for name, value in content_types %}'{{ value }}': '{{ name }}'{% if not forloop.last %},{% endif %}
{% endfor %}};
$(document).ready(function(){
// move contents into their corresponding regions and do some simple formatting
$("div[id$=_set]").children().each(function(){
var elem = $(this);
if (!(elem.hasClass("header"))) {
elem.find("input[name$=-region]").addClass("region-choice-field");
elem.find("input[name$=-DELETE]").addClass("delete-field").parents("div.form-row").hide();
elem.find("input[name$=-ordering]").addClass("order-field");
var region_id = elem.find(".region-choice-field").val();
region_id = REGION_MAP.indexOf(region_id);
var content_type = elem.attr("id").substr(0, elem.attr("id").indexOf("_"));
region_append(region_id,elem, CONTENT_NAMES[content_type]);
set_item_field_value(elem,"region-choice-field",region_id)
}
});
// register regions as sortable for drag N drop
$(".order-machine").sortable({
handle: '.handle',
helper: 'clone',
placeholder: 'highlight',
stop: function(event, ui) {
richify_poor($(ui.item));
}
});
attach_dragdrop_handlers();
if(window.location.hash) {
$('#'+window.location.hash.substr(5)+'_tab').trigger('click');
}
// bring order to chaos
zucht_und_ordnung(true);
{% block extra-init-js %}{# /* do not use this block, use feincms_item_editor_includes instead */ #}{% endblock %}
$('#inlines').hide();
});
$(window).load(function(){init_contentblocks()});
</script>
<link rel="stylesheet" type="text/css" href="{{ FEINCMS_ADMIN_MEDIA }}css/layout.css" />
<link rel="stylesheet" type="text/css" href="{{ FEINCMS_ADMIN_MEDIA }}css/jquery.alerts.css" media="screen" />
{% endblock %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="../../../">{% trans "Home" %}</a> &rsaquo;
<a href="../../">{{ opts.app_label|capfirst|escape }}</a> &rsaquo;
<a href="../">{{ opts.verbose_name_plural|capfirst }}</a> &rsaquo;
{{ object.title|truncatewords:"18" }}
</div>
{% endblock %}
{% block content %}
<div id="content-main">
{% block object-tools %}
<ul class="object-tools">
{% if object.get_absolute_url %}
<li><a target="_blank" href="{{ object.get_absolute_url }}" class="viewsitelink">{% trans "View on site" %}</a></li>
{% endif %}
</ul>
{% endblock %}
<form name="main_form" enctype="multipart/form-data" action="." method="post" id="{{ opts.module_name }}_form">
<div>
<div class="submit-row" >
<input type="submit" value="{% trans "Save" %}" class="default" name="_save" />
<p class="deletelink-box"><a href="delete/" class="deletelink">{% trans "Delete" %}</a></p>
<input type="submit" value="Sichern und neu hinzufügen" name="_addanother" />
<input type="submit" value="{% trans "Save and continue editing" %}" name="_continue" />
</div>
<fieldset class="module aligned">
{% for field in top_fieldset %}
<div class="form-row{% if field.errors %} errors{% endif %}">
{% ifequal field.name "language" %}
{# Maybe this should be moved somewhere else, since this is specific for translated objects... #}
{% with object.available_translations as translations %}
{% if translations %}
<div style="float:right;padding:5px 0 0 0">
{% trans "available translations" %}:
{% for translation in translations %}
<a href="../{{ translation.id }}/">{{ translation.language|upper }}</a>{% if not forloop.last %},{% endif %}
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% endifequal %}
{{ field.label_tag }}{{ field }}
{% if field.field.help_text %}<p class="help">{{ field.field.help_text|safe }}</p>{% endif %}
</div>
{% endfor %}
{% if object_form.template_key %} {# Maybe this should be moved somewhere else, since this is page-module-specific #}
<div class="form-row{% if field.errors %} errors{% endif %}">
{{ object_form.template_key.label_tag }}
<span>{{ object_form.template_key }}{{ object_form.template_key.errors }}</span>
<input type="button" class="change-template" value="{% trans 'Change Template' %}" />
</div>
{% endif %}
</fieldset>
<div id="main_wrapper">
<div class="navi_tab tab_active" id="settings_tab">{% trans "Properties" %}</div>
{% for region in object.template.regions %}
<div class="navi_tab" id="{{ region.key }}_tab">{{ region.title }}</div>
{% endfor %}
<div id="main">
<fieldset class="module aligned" id="settings_body">
{% for field in settings_fieldset %}
<div class="form-row{% if field.errors %} errors{% endif %}">
{{ field.label_tag }}{{ field }}
{% if field.field.help_text %}<p class="help">{{ field.field.help_text|safe }}</p>{% endif %}
</div>
{% endfor %}
</fieldset>
{% for region in object.template.regions %}
<div id="{{ region.key }}_body" class="panel">
<div class="empty-machine-msg">
{% trans "Region empty" %}
</div>
<div class="empty-machine-msg" style="margin-left:20px; margin-top:20px;">
{% if region.inherited %}
{% trans "Content from the parent site is automatically inherited. To override this behaviour, add some content." %}
{% endif %}
</div>
<div class="order-machine"></div>
<div class="machine-control">
<div class="control-unit">
<span>{% trans "Add new item" %}:</span> <br/>
<select name="order-machine-add-select">
{% for n,v in content_types %} <option value="{{ v }}">{{ n }}</option> {% endfor %}
</select>
<input type="button" class="order-machine-add-button button" value="OK" />
</div>
<div class="control-unit">
<span>{% trans "Move selected item to" %}:</span> <br/>
<select name="order-machine-move-select">
{% for r in object.template.regions %} {% ifnotequal region r %} <option value="{{ r.key }}">{{ r.title }}</option> {% endifnotequal %} {% endfor %}
</select>
<input type="button" class="order-machine-move-button button" value="{% trans "OK" %}" />
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="submit-row" >
<input type="submit" value="{% trans "Save" %}" class="default" name="_save" />
<p class="deletelink-box"><a href="delete/" class="deletelink">{% trans "Delete" %}</a></p>
<input type="submit" value="Sichern und neu hinzufügen" name="_addanother" />
<input type="submit" value="{% trans "Save and continue editing" %}" name="_continue" />
</div>
<div id="inlines">
{% for formset in inline_formsets %}
<div id="{{ formset.rel_name }}">
<div class="header">
{{ formset.management_form }}
</div>
{% for form in formset.forms %}
<div id="{{ formset.rel_name }}_item_{{ forloop.counter0 }}">
{% for field in form %}
{% if field.is_hidden %}
{{ field }}
{% else %}
<div class="form-row{% if field.errors %} errors{% endif %}">
{{ field.label_tag }}{{ field }}
{% if field.field.help_text %}<p class="help">{{ field.field.help_text|safe }}</p>{% endif %}
</div>
{% endif %}
{% endfor %}
</div>
{% endfor %}
</div>
{% endfor %}
</div>
</div>
</form>
</div>
{% endblock %}

View file

@ -0,0 +1,81 @@
{% load i18n %}
<div id="fe_tools">
<a id="fe_tools_edit" href="#">{% trans "edit" %}</a>
<!--
<a id="fe_tools_new" href="#">{% trans "new" %}</a>
<a id="fe_tools_up" href="#">{% trans "up" %}</a>
<a id="fe_tools_down" href="#">{% trans "down" %}</a>
<a id="fe_tools_remove" href="#">{% trans "remove" %}</a>
-->
</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
var admin_base = '/admin/page/page/';
fe_init_animations();
var fe_tools = $('#fe_tools');
fe_tools.children('a').click(function(){
var fe_box = $(this).parents('div.fe_box');
if(this.id=='fe_tools_edit') {
res = fe_box.attr('id').match(/([^\-]+)-(\d+)-(\d+)/);
window.open(admin_base+res[2]+'/'+res[1]+'/'+res[3]+'/',
'fe_editor',
'height=500,width=800,resizable=yes,scrollbars=yes');
}
return false;
});
});
function fe_init_animations() {
var fe_tools = $('#fe_tools');
$('.fe_box').hover(function(){
$(this).append(fe_tools).css('background', '#e8e8ff').animate({'opacity': 1}, 100);
fe_tools.show();
}, function(){
$(this).animate({'opacity': 0.6}, 100).css('background', 'none');
fe_tools.hide();
});
}
function fe_update_content(identifier, content) {
var region = $('#'+identifier);
region.animate({'opacity': 0}).html(content);
region.animate({'opacity': 1.5}).animate({'opacity': 0.6});
fe_init_animations();
}
</script>
<style type="text/css">
.fe_box {
position: relative;
opacity: 0.6;
}
#fe_tools {
background: #fff;
border: 1px solid #000;
padding: 13px 5 13px 15px;
display: none;
position: absolute;
left: 10px;
bottom: -25px;
font-size: 70%;
opacity: 0.8;
}
#fe_tools a {
background: #000;
color: #fff;
text-decoration: none;
margin: 0 10px 0 0;
padding: 4px 5px;
display: block;
float: left;
}
</style>

View file

@ -0,0 +1,167 @@
{% extends "admin/change_list.html" %}
{% load i18n admin_modify adminmedia %}
{% block title %}{{ block.super }}{% endblock %}
{% block extrahead %}{{ block.super }}
<script type="text/javascript" src="../../../jsi18n/"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>
<script type="text/javascript" src="{{ EDITOR_ADMIN_MEDIA }}jquery.livequery.js"></script>
<script type="text/javascript" src="{{ EDITOR_ADMIN_MEDIA }}jquery.alerts.js"></script>
<script type="text/javascript" src="{{ EDITOR_ADMIN_MEDIA }}helper.js"></script>
<script type="text/javascript" src="{{ EDITOR_ADMIN_MEDIA }}listener.js"></script>
<script type="text/javascript" src="{{ EDITOR_ADMIN_MEDIA }}jquery.treeTable.js"></script>
<script type="text/javascript" src="{{ EDITOR_ADMIN_MEDIA }}jquery.json-1.3.js"></script>
<script type="text/javascript">
{% include "admin/editor/_messages.html" %}
ancestors = [{% for item in object_list %}'{{ item.parent_id|default_if_none:"0" }}'{% if not forloop.last %}, {% endif %}{% endfor %}];
tablestr = '';
{% for item, title, item_properties in tree_editor.object_list %}
tablestr += add_row({{ forloop.counter }}, {{ item.id }}, "{{ item.parent_id|default_if_none:"-1" }}", "{{ title|escapejs }}",
[{% for property in item_properties %}"{{ property|escapejs }}"{% if not forloop.last %}, {% endif %}{% endfor %}]);{% endfor %}
function add_row(node_id, item_id, parent_id, item_title, attrs) {
var str = '<tr id="node-' + node_id + '" class="item-id-' + item_id + ' ';
if (parseInt(parent_id) >= 0)
str += 'child-of-node-'+ancestors.indexOf(parent_id);
str += '">';
str += '<td><div class="wrap nohover">';
str += '<div class="insert-as-child"></div>';
str += '<span class="title-col"><a href="'+item_id+'/"><strong>'+item_title+'</strong></a><img class="move-node" src="{{ EDITOR_ADMIN_MEDIA }}img/icon_move.gif" /></span>';
str += '<div class="insert-as-sibling"></div>';
str += '</div></td>';
for (key in attrs)
str += attrs[key];
str += '<td><img class="del-page" src="{{ EDITOR_ADMIN_MEDIA }}img/icon_deletelink.gif"/></td></tr>';
return str;
}
$(document).ready(function() {
// build table
$("#sitetree tbody").append(tablestr);
// register
$("#sitetree").treeTable();
// configure draggable
$("#sitetree .title-col").draggable({
helper: function(){ return $(this).parent().clone(); } ,
handle: ".move-node",
opacity: .75,
refreshPositions: true,
revert: "invalid",
revertDuration: 300,
scroll: true
});
// configure droppable to insert as child
$("#sitetree .insert-as-child").each(function() {
$(this).droppable({
accept: ".title-col",
tolerance: "intersect",
drop: function(e, ui) {
handle_drop_event($(ui.draggable).parents("tr"), $(this).parents("tr"), "child")
},
over: function(e, ui) {
$(this).parent().removeClass("nohover").addClass("hover-as-child");
},
out: function(e, ui) {
$(this).parent().removeClass("hover-as-child").addClass("nohover");
}
});
});
// configure droppable to insert as sibling
$("#sitetree .insert-as-sibling").each(function() {
$(this).droppable({
accept: ".title-col",
tolerance: "intersect",
drop: function(e, ui) {
handle_drop_event($(ui.draggable).parents("tr"), $(this).parents("tr"), "sibling")
},
over: function(e, ui) {
var row = '<div style="background-color:#bcf; height:4px; width:100%; margin:-8px 0px 4px -5px; position:relative; z-index:10;"></div>'
$(row).insertBefore($(this).parent());
},
out: function(e, ui) {
$(this).parent().prev().remove();
}
});
});
$(".wrap").live('click',function() {
if ($(this).find(".expander").length > 0)
$(this).parents("tr").toggleBranch();
});
$(".save_tree").click(function(){
save_page_tree();
});
$(".del-page").click(function(){
handle_page_delete($(this).parents("tr"));
});
});
function expandall(yesno) {
if(yesno) {
var elems = $('#sitetree tr.collapsed');
if(elems.length)
elems.expand().removeClass('collapsed').addClass('expanded');
} else {
var elems = $('#sitetree tr.expanded');
for(var i=elems.length; i>=0; i--)
$(elems[i]).collapse().removeClass('expanded').addClass('collapsed');
}
return false;
}
</script>
<link rel="stylesheet" type="text/css" href="{{ EDITOR_ADMIN_MEDIA }}css/layout.css" />
<link rel="stylesheet" type="text/css" href="{{ EDITOR_ADMIN_MEDIA }}css/jquery.alerts.css" media="screen" />
<link href="{{ EDITOR_ADMIN_MEDIA }}css/jquery.treeTable.css" rel="stylesheet" type="text/css" />
{% endblock %}
{% block content %}
<div id="content-main">
{% block object-tools %}
{% if has_add_permission %}
<ul class="object-tools"><li><a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink">{% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %}</a></li></ul>
{% endif %}
{% endblock %}
<input type="button" value="{% trans "Save tree" %}" class="save_tree" style="float:right;margin:0 1px 0 0" />
<div style="padding-top: 10px;">
<a href="#" onclick="return expandall(1)">{% trans "Expand all" %}</a>
<a href="#" onclick="return expandall(0)">{% trans "Collapse all" %}</a>
</div>
<div id="sitetree-wrapper" style="clear:both">
<table id="sitetree" border="1">
<thead>
<tr id="table_header">
{% for header in result_headers %}
<th{% if forloop.first %} style="min-width:400px"{% endif %}>{{ header.text|capfirst }}
{% endfor %}
<th>{% trans "Delete" %}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
{% endblock %}