Making sure everything is in the repo
|
|
@ -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)
|
||||
|
|
|
|||
BIN
categories/media/css/images/title.gif
Normal file
|
After Width: | Height: | Size: 317 B |
54
categories/media/css/jquery.alerts.css
Normal 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;
|
||||
}
|
||||
47
categories/media/css/jquery.treeTable.css
Normal 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;
|
||||
}
|
||||
217
categories/media/css/layout.css
Normal 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;
|
||||
}
|
||||
85
categories/media/helper.js
Normal 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"));
|
||||
});
|
||||
}
|
||||
BIN
categories/media/img/arrow_down.gif
Normal file
|
After Width: | Height: | Size: 224 B |
BIN
categories/media/img/arrow_right.gif
Normal file
|
After Width: | Height: | Size: 222 B |
BIN
categories/media/img/circle.gif
Normal file
|
After Width: | Height: | Size: 198 B |
BIN
categories/media/img/cut.png
Normal file
|
After Width: | Height: | Size: 648 B |
BIN
categories/media/img/default-bg.gif
Normal file
|
After Width: | Height: | Size: 844 B |
BIN
categories/media/img/door.png
Normal file
|
After Width: | Height: | Size: 412 B |
BIN
categories/media/img/help.gif
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
categories/media/img/icon_deletelink.gif
Normal file
|
After Width: | Height: | Size: 181 B |
BIN
categories/media/img/icon_move.gif
Executable file
|
After Width: | Height: | Size: 185 B |
BIN
categories/media/img/important.gif
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
categories/media/img/info.gif
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
categories/media/img/nav-bg.gif
Normal file
|
After Width: | Height: | Size: 273 B |
BIN
categories/media/img/page_white_copy.png
Normal file
|
After Width: | Height: | Size: 309 B |
BIN
categories/media/img/page_white_delete.png
Normal file
|
After Width: | Height: | Size: 536 B |
BIN
categories/media/img/page_white_edit.png
Normal file
|
After Width: | Height: | Size: 618 B |
BIN
categories/media/img/page_white_paste.png
Normal file
|
After Width: | Height: | Size: 620 B |
BIN
categories/media/img/title.gif
Normal file
|
After Width: | Height: | Size: 317 B |
BIN
categories/media/img/toggle-collapse-dark.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
categories/media/img/toggle-collapse-light.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
categories/media/img/toggle-expand-dark.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
categories/media/img/toggle-expand-light.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
54
categories/media/jquery.alerts.css
Normal 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;
|
||||
}
|
||||
235
categories/media/jquery.alerts.js
Normal 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: ' OK ', // text for the OK button
|
||||
cancelButton: ' Cancel ', // 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);
|
||||
156
categories/media/jquery.json-1.3.js
Normal 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);
|
||||
250
categories/media/jquery.livequery.js
Normal 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);
|
||||
384
categories/media/jquery.treeTable.js
Normal 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();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
87
categories/media/listener.js
Normal 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;
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -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'])
|
||||
|
|
|
|||
8
categories/templates/admin/editor/_messages.html
Normal 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." %}"];
|
||||
1
categories/templates/admin/editor/box.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
<div class="fe_box" id="{{ identifier }}">{{ content|safe }}</div>
|
||||
57
categories/templates/admin/editor/editor.html
Normal 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 %}
|
||||
12
categories/templates/admin/editor/editor_done.html
Normal 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>
|
||||
252
categories/templates/admin/editor/item_editor.html
Normal 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> ›
|
||||
<a href="../../">{{ opts.app_label|capfirst|escape }}</a> ›
|
||||
<a href="../">{{ opts.verbose_name_plural|capfirst }}</a> ›
|
||||
{{ 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 %}
|
||||
|
||||
81
categories/templates/admin/editor/tools.html
Normal 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>
|
||||
167
categories/templates/admin/editor/tree_editor.html
Normal 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 %}
|
||||