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.contrib import admin
|
||||||
from django import forms
|
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):
|
class CategoryAdminForm(forms.ModelForm):
|
||||||
required_if_other_not_given = {
|
parent = TreeNodeChoiceField(queryset=Category.tree.all(), level_indicator=u'+-', required=False)
|
||||||
'hierarchy': 'parent',
|
|
||||||
'parent': 'hierarchy',
|
|
||||||
}
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Category
|
model = Category
|
||||||
|
|
||||||
def clean_name(self):
|
def clean_slug(self):
|
||||||
if '/' in self.cleaned_data['name']:
|
self.cleaned_data['slug'] = slugify(self.cleaned_data['name'])
|
||||||
raise forms.ValidationError, "A category name can't contain slashes."
|
return self.cleaned_data['slug']
|
||||||
return self.cleaned_data['name']
|
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
super(CategoryAdminForm, self).clean()
|
super(CategoryAdminForm, self).clean()
|
||||||
|
|
||||||
if 'slug' in self.cleaned_data and 'parent' in self.cleaned_data and 'hierarchy' in self.cleaned_data:
|
# Validate slug is valid in that level
|
||||||
if self.cleaned_data['parent'] is not None:
|
kwargs = {}
|
||||||
# inherit from parent
|
if self.cleaned_data.get('parent', None) is None:
|
||||||
self.cleaned_data['hierarchy'] = self.cleaned_data['parent'].hierarchy
|
kwargs['parent__isnull'] = True
|
||||||
|
|
||||||
#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
|
|
||||||
else:
|
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
|
form=CategoryAdminForm
|
||||||
fields = ('hierarchy', 'parent', 'name', 'slug')
|
|
||||||
list_display = ('__unicode__',)
|
list_display = ('__unicode__',)
|
||||||
list_filter = ('hierarchy',)
|
search_fields = (('name',))
|
||||||
search_fields = ('name', 'path')
|
|
||||||
prepopulated_fields = {'slug': ('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(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
|
from django.utils.encoding import force_unicode
|
||||||
import mptt
|
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):
|
class Category(models.Model):
|
||||||
category_tree = models.ForeignKey(CategoryTree,
|
|
||||||
blank=False,
|
|
||||||
null=False
|
|
||||||
related_name="categories")
|
|
||||||
parent = models.ForeignKey('self',
|
parent = models.ForeignKey('self',
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
related_name="children",
|
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')
|
verbose_name='Parent')
|
||||||
name = models.CharField(max_length=100)
|
name = models.CharField(max_length=100)
|
||||||
|
order = models.IntegerField(blank=True, null=True)
|
||||||
slug = models.SlugField()
|
slug = models.SlugField()
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
|
|
@ -46,10 +24,10 @@ class Category(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name_plural = 'categories'
|
verbose_name_plural = 'categories'
|
||||||
unique_together = (('parent', 'name'),)
|
unique_together = (('parent', 'name'),)
|
||||||
ordering = ('category_tree__name','parent__name','name')
|
ordering = ('name',)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
ancestors = self.get_ancestors()
|
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'])
|
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 %}
|
||||||