Bugfix on permissions verification (on domain admin was able to access any domain :p)

Added help tips when filling forms (domain, mailbox, etc.)
French translation update.

Tips class added to mootools-more.js is not the official version (1.2.4.2). There are some bugs with this version so I've decided to integrate modifications coming from here : https://mootools.lighthouseapp.com/projects/24057/tickets/167-tips-class-issues-in-more-1242
This commit is contained in:
tonio
2009-10-30 11:28:40 +01:00
parent f05cd1ffeb
commit 3fe149adb0
22 changed files with 451 additions and 108 deletions
+12 -6
View File
@@ -14,10 +14,13 @@ class DomainForm(forms.ModelForm):
class MailboxForm(forms.ModelForm):
quota = forms.IntegerField(label=_("Quota"), required=False)
password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
password2 = forms.CharField(label=_("Confirmation"), widget=forms.PasswordInput)
password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput,
help_text=_("Password used to log in"))
password2 = forms.CharField(label=_("Confirmation"), widget=forms.PasswordInput,
help_text=_("Password confirmation"))
enabled = forms.BooleanField(label=gender("Enabled", "f"), required=False,
initial=True)
initial=True,
help_text=_("Check to activate this mailbox"))
class Meta:
model = Mailbox
@@ -50,8 +53,11 @@ class AliasForm(forms.ModelForm):
class PermissionForm(forms.Form):
domain = forms.ModelChoiceField(queryset=Domain.objects.all(), label=_("Domain"),
required=True)
user = forms.ChoiceField(label=_("User"), required=True)
required=True,
help_text=_("Select a domain in the list"))
user = forms.ChoiceField(label=_("User"), required=True,
help_text=_("Select a user in the list"))
role = forms.ChoiceField(label=_("Role"), required=True,
choices=(("SuperAdmins", _("Super administrator")),
("DomainAdmins", _("Domain administrator"))))
("DomainAdmins", _("Domain administrator"))),
help_text=_("Select the role you want this user to have"))
+16 -9
View File
@@ -6,9 +6,11 @@ from mailng.lib import exec_pipe, exec_as_vuser
import os
class Domain(models.Model):
name = models.CharField(_('name'), max_length=100)
quota = models.IntegerField()
enabled = models.BooleanField(_('enabled'))
name = models.CharField(_('name'), max_length=100,
help_text=_("The domain name"))
quota = models.IntegerField(help_text=_("Default quota in MB applied to mailboxes"))
enabled = models.BooleanField(_('enabled'),
help_text=_("Check to activate this domain"))
class Meta:
permissions = (
@@ -33,11 +35,13 @@ class Domain(models.Model):
return self.name
class Mailbox(models.Model):
name = models.CharField(_('name'), max_length=100)
address = models.CharField(_('address'), max_length=100)
name = models.CharField(_('name'), max_length=100,
help_text=_("First name and last name of mailbox owner"))
address = models.CharField(_('address'), max_length=100,
help_text=_("Mailbox address (without the @domain.tld part)"))
full_address = models.CharField(max_length=150)
password = models.CharField(_('password'), max_length=100)
quota = models.IntegerField()
quota = models.IntegerField(help_text=_("Mailbox quota in MB (default to domain quota if blank)"))
uid = models.IntegerField()
gid = models.IntegerField()
path = models.CharField(max_length=200)
@@ -99,10 +103,13 @@ class Mailbox(models.Model):
self.domain.name, self.address))
class Alias(models.Model):
address = models.CharField(_('address'), max_length=100)
address = models.CharField(_('address'), max_length=100,
help_text=_("The alias address (without the domain part)"))
full_address = models.CharField(max_length=150)
mbox = models.ForeignKey(Mailbox, verbose_name=_('mailbox'))
enabled = models.BooleanField(_('enabled'))
mbox = models.ForeignKey(Mailbox, verbose_name=_('mailbox'),
help_text=_("The mailbox this alias points to"))
enabled = models.BooleanField(_('enabled'),
help_text=_("Check to activate this alias"))
class Meta:
permissions = (
+27 -6
View File
@@ -4,6 +4,7 @@ from django.template import RequestContext
from django.http import HttpResponse, HttpResponseRedirect
from django.utils import simplejson
from django.utils.translation import ugettext as _
from django.utils.http import urlquote
from django.core import serializers
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators \
@@ -23,6 +24,21 @@ def is_superuser(user):
return False
return True
def good_domain(f):
def dec(request, dom_id, **kwargs):
if request.user.is_superuser:
return f(request, dom_id, **kwargs)
mb = Mailbox.objects.get(user=request.user.id)
domid = isinstance(dom_id, str) and "%d" % dom_id or dom_id
if domid == mb.domain.id:
return f(request, domid, **kwargs)
from django.conf import settings
path = urlquote(request.get_full_path())
login_url = settings.LOGIN_URL
return HttpResponseRedirect("%s?next=%s" % (login_url, path))
return dec
@login_required
def domains(request):
if not request.user.has_perm("admin.view_domains"):
@@ -41,10 +57,8 @@ def domains(request):
})
@login_required
@permission_required("admin.add_mailbox")
@permission_required("admin.add_domain")
def newdomain(request):
if not is_superuser(request.user):
return mailboxes(request, dom_id)
if request.method == "POST":
form = DomainForm(request.POST)
error = None
@@ -71,10 +85,8 @@ def newdomain(request):
})
@login_required
@permission_required("admin.change_mailbox")
@permission_required("admin.change_domain")
def editdomain(request, dom_id):
if not is_superuser(request.user):
return mailboxes(request, dom_id)
domain = Domain.objects.get(pk=dom_id)
if request.method == "POST":
form = DomainForm(request.POST, instance=domain)
@@ -110,6 +122,7 @@ def deldomain(request, dom_id):
return HttpResponseRedirect('/mailng/admin/')
@login_required
@good_domain
@permission_required("admin.view_mailboxes")
def mailboxes(request, dom_id=None):
domain = Domain.objects.get(pk=dom_id)
@@ -119,6 +132,7 @@ def mailboxes(request, dom_id=None):
})
@login_required
@good_domain
@permission_required("admin.view_mailboxes")
def mailboxes_raw(request, dom_id=None):
mailboxes = Mailbox.objects.filter(domain=dom_id)
@@ -127,6 +141,7 @@ def mailboxes_raw(request, dom_id=None):
})
@login_required
@good_domain
@permission_required("admin.add_mailbox")
def newmailbox(request, dom_id=None):
domain = Domain.objects.get(pk=dom_id)
@@ -183,6 +198,7 @@ def newmailbox(request, dom_id=None):
})
@login_required
@good_domain
@permission_required("admin.change_mailbox")
def editmailbox(request, dom_id, mbox_id=None):
mb = Mailbox.objects.get(pk=mbox_id)
@@ -231,6 +247,7 @@ def editmailbox(request, dom_id, mbox_id=None):
})
@login_required
@good_domain
@permission_required("admin.delete_mailbox")
def delmailbox(request, dom_id, mbox_id=None):
mb = Mailbox.objects.get(pk=mbox_id)
@@ -246,6 +263,7 @@ def delmailbox(request, dom_id, mbox_id=None):
# args=[dom_id]))
@login_required
@good_domain
@permission_required("admin.view_aliases")
def aliases(request, dom_id=None, mbox_id=None):
domain = Domain.objects.get(pk=dom_id)
@@ -261,6 +279,7 @@ def aliases(request, dom_id=None, mbox_id=None):
})
@login_required
@good_domain
@permission_required("admin.add_alias")
def newalias(request, dom_id, mbox_id):
mbox = Mailbox.objects.get(pk=mbox_id)
@@ -289,6 +308,7 @@ def newalias(request, dom_id, mbox_id):
})
@login_required
@good_domain
@permission_required("admin.change_alias")
def editalias(request, dom_id, alias_id):
alias = Alias.objects.get(pk=alias_id)
@@ -318,6 +338,7 @@ def editalias(request, dom_id, alias_id):
})
@login_required
@good_domain
@permission_required("admin.delete_alias")
def delalias(request, dom_id, alias_id):
alias = Alias.objects.get(pk=alias_id)
+1 -2
View File
@@ -83,13 +83,12 @@ def render_listing(request, cursor):
"subject" : row[2], "content" : row[3],
"mailid" : row[4], "time" : datetime.fromtimestamp(row[5]),
"type" : row[6]})
paginator = Paginator(emails, 10)
try:
pagenum = int(request.GET.get('page', '1'))
except ValueError:
pagenum = 1
page = paginator.page(pagenum)
page = paginator.page(pagenum)
return render_to_string("amavis_quarantine/listing.html", {
"count" : len(rows),
"emails" : page, "current_page" : pagenum,
@@ -106,13 +106,15 @@ window.addEvent("domready", function() {
mysubmit(event, "release");
});
$("selectall").addEvent("click", function(event) {
if ($("selectall").checked) {
toggleSelection(true);
} else {
toggleSelection(false);
}
});
if ($("selectall")) {
$("selectall").addEvent("click", function(event) {
if ($("selectall").checked) {
toggleSelection(true);
} else {
toggleSelection(false);
}
});
}
{% url extensions.amavis_quarantine.main.search as s_url %}
$("searchfield").addEvent("change", function(event) {
@@ -1,5 +1,8 @@
{% load i18n %}
{% if not count %}
<div id="notifybox">{% trans "No messages in quarantine" %}</div>
{% else %}
<div id="listheader">
<div id="counter">
Messages {{ emails.start_index }} à {{ emails.end_index }} sur {{ count }}
@@ -43,4 +46,6 @@
<td>{{ m.time }}</td>
</tr>
{% endfor %}
</table>
</table>
{% endif %}
+121 -42
View File
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-10-29 14:54+0100\n"
"POT-Creation-Date: 2009-10-30 11:19+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -25,93 +25,154 @@ msgstr ""
msgid "Password"
msgstr "Mot de passe"
#: admin/forms.py:18 main/forms.py:21
#: admin/forms.py:18
msgid "Password used to log in"
msgstr "Mot de passe utilisé pour se connecter"
#: admin/forms.py:19 main/forms.py:21
msgid "Confirmation"
msgstr ""
#: admin/forms.py:33 main/forms.py:36
#: admin/forms.py:20
msgid "Password confirmation"
msgstr "Confirmation du mot de passe"
#: admin/forms.py:23
msgid "Check to activate this mailbox"
msgstr "Cocher pour activer cette boite aux lettres"
#: admin/forms.py:36 main/forms.py:36
msgid "Passwords mismatch"
msgstr "Les mots de passe diffèrent"
#: admin/forms.py:52 templates/admin/domain_header.html:7
#: admin/forms.py:55 templates/admin/domain_header.html:7
#: templates/admin/editdomain.html:7 templates/admin/permissions.html:42
msgid "Domain"
msgstr "Domaine"
#: admin/forms.py:54
#: admin/forms.py:57
msgid "Select a domain in the list"
msgstr "Sélectionner un domaine dans la liste"
#: admin/forms.py:58
msgid "User"
msgstr "Utilisateur"
#: admin/forms.py:55
#: admin/forms.py:59
msgid "Select a user in the list"
msgstr "Sélectionner un utilisateur dans la liste"
#: admin/forms.py:60
msgid "Role"
msgstr "Rôle"
#: admin/forms.py:56
#: admin/forms.py:61
msgid "Super administrator"
msgstr "Super administrateur"
#: admin/forms.py:57
#: admin/forms.py:62
msgid "Domain administrator"
msgstr "Admin. de domaine"
#: admin/models.py:9 admin/models.py:36
#: admin/forms.py:63
msgid "Select the role you want this user to have"
msgstr "Sélectionner le rôle souhaité pour cet utilisateur"
#: admin/models.py:9 admin/models.py:38
msgid "name"
msgstr "Nom"
#: admin/models.py:11 admin/models.py:105 main/models.py:9
#: admin/models.py:10
msgid "The domain name"
msgstr "Le nom du domaine"
#: admin/models.py:11
msgid "Default quota in MB applied to mailboxes"
msgstr "Quota par défaut en Mo appliqué aux boites aux lettres"
#: admin/models.py:12 admin/models.py:111 main/models.py:9
msgid "enabled"
msgstr "Activé"
#: admin/models.py:37 admin/models.py:102
#: admin/models.py:13
msgid "Check to activate this domain"
msgstr "Cocher pour activer ce domaine"
#: admin/models.py:39
msgid "First name and last name of mailbox owner"
msgstr "Prénom et nom du propriétaire de la boite aux lettres"
#: admin/models.py:40 admin/models.py:106
msgid "address"
msgstr "Adresse"
#: admin/models.py:39
#: admin/models.py:41
msgid "Mailbox address (without the @domain.tld part)"
msgstr "Adresse de la boite aux lettres (sans la partie @domain.tld)"
#: admin/models.py:43
msgid "password"
msgstr "Mot de passe"
#: admin/models.py:104
#: admin/models.py:44
msgid "Mailbox quota in MB (default to domain quota if blank)"
msgstr ""
"Quota en Mo de la boite aux lettres (par défaut celui du domaine si vide)"
#: admin/models.py:107
msgid "The alias address (without the domain part)"
msgstr "L'adresse de l'alias (sans la partie domaine)"
#: admin/models.py:109
msgid "mailbox"
msgstr "Boite aux lettres"
#: admin/views.py:22
#: admin/models.py:110
msgid "The mailbox this alias points to"
msgstr "La boite aux lettres sur laquelle pointe cet alias"
#: admin/models.py:112
msgid "Check to activate this alias"
msgstr "Cocher pour activer cet alias"
#: admin/views.py:23
msgid "Permission denied."
msgstr "Permission refusée."
#: admin/views.py:53 admin/views.py:85
#: admin/views.py:67 admin/views.py:97
msgid "Domain with this name already defined"
msgstr "Un domaine avec ce nom existe déjà"
#: admin/views.py:62
#: admin/views.py:76
msgid "Failed to initialise domain, check permissions"
msgstr "Impossible d'initialiser le domaine, vérifier les permissions"
#: admin/views.py:88
#: admin/views.py:100
msgid "Failed to rename domain, check permissions"
msgstr "Impossible de renommer le domaine, vérifier les permissions"
#: admin/views.py:139 admin/views.py:197
#: admin/views.py:154 admin/views.py:213
msgid "Mailbox with this address already exists"
msgstr "Une boite aux lettres pour cette adresse existe déjà"
#: admin/views.py:170
#: admin/views.py:185
msgid "Mailbox created."
msgstr "Boite aux lettres créé."
#: admin/views.py:174
#: admin/views.py:189
msgid "Failed to initialise mailbox, check permissions"
msgstr ""
"Impossible d'initialiser la boite aux lettres, vérifier les permissions"
#: admin/views.py:200
#: admin/views.py:216
msgid "Failed to rename mailbox, check permissions"
msgstr "Impossible de renommer la boite aux lettres, vérifier les permissions."
#: admin/views.py:273 admin/views.py:302
#: admin/views.py:292 admin/views.py:322
msgid "Alias with this address already exists"
msgstr "Un alias avec cette adresse existe déjà"
#: admin/views.py:374
#: admin/views.py:395
msgid "admin is intouchable!!"
msgstr "admin est intouchable!!"
@@ -140,16 +201,16 @@ msgid "Properties"
msgstr "Propriétés"
#: extensions/amavis_quarantine/main.py:49
#: extensions/amavis_quarantine/templates/index.html:151
#: extensions/amavis_quarantine/templates/index.html:153
msgid "Quarantine"
msgstr "Quarantaine"
#: extensions/amavis_quarantine/main.py:226
#: extensions/amavis_quarantine/main.py:227
#, python-format
msgid "%(count)d message%(plural)s deleted successfully"
msgstr "%(count)d message%(plural)s supprimé correctement"
#: extensions/amavis_quarantine/main.py:264
#: extensions/amavis_quarantine/main.py:267
#, fuzzy, python-format
msgid "%(count)d message%(plural)s released successfully"
msgstr "%(count)d messages relâché correctement"
@@ -162,50 +223,53 @@ msgstr "Supprimer cette sélection?"
msgid "Release this selection?"
msgstr "Relâcher cette sélection?"
#: extensions/amavis_quarantine/templates/index.html:134
#: extensions/amavis_quarantine/templates/index.html:156
#: extensions/amavis_quarantine/templates/index.html:136
#: extensions/amavis_quarantine/templates/index.html:158
msgid "Search..."
msgstr "Chercher..."
#: extensions/amavis_quarantine/templates/index.html:158
#, fuzzy
#: extensions/amavis_quarantine/templates/index.html:160
msgid "From address"
msgstr "Emetteur"
#: extensions/amavis_quarantine/templates/index.html:159
#: extensions/amavis_quarantine/templates/listing.html:32
#: extensions/amavis_quarantine/templates/index.html:161
#: extensions/amavis_quarantine/templates/listing.html:35
msgid "Subject"
msgstr "sujet"
msgstr "Sujet"
#: extensions/amavis_quarantine/templates/index.html:160
#: extensions/amavis_quarantine/templates/index.html:162
msgid "Both"
msgstr "Tous"
#: extensions/amavis_quarantine/templates/listing.html:10
#: extensions/amavis_quarantine/templates/listing.html:4
msgid "No messages in quarantine"
msgstr "Aucun message dans la quarantaine"
#: extensions/amavis_quarantine/templates/listing.html:13
msgid "First"
msgstr "Première"
#: extensions/amavis_quarantine/templates/listing.html:13
#: extensions/amavis_quarantine/templates/listing.html:16
msgid "Previous"
msgstr "Précédente"
#: extensions/amavis_quarantine/templates/listing.html:18
#: extensions/amavis_quarantine/templates/listing.html:21
msgid "Next"
msgstr "Suivante"
#: extensions/amavis_quarantine/templates/listing.html:21
#: extensions/amavis_quarantine/templates/listing.html:24
msgid "Last"
msgstr "Dernière"
#: extensions/amavis_quarantine/templates/listing.html:30
#: extensions/amavis_quarantine/templates/listing.html:33
msgid "Type"
msgstr ""
#: extensions/amavis_quarantine/templates/listing.html:31
#: extensions/amavis_quarantine/templates/listing.html:34
msgid "From"
msgstr "De"
#: extensions/amavis_quarantine/templates/listing.html:33
#: extensions/amavis_quarantine/templates/listing.html:36
msgid "Date"
msgstr ""
@@ -271,6 +335,22 @@ msgstr ""
msgid "Auto-reply message"
msgstr "Message de réponse automatique"
#: extensions/stats/main.py:39
msgid "Statistics"
msgstr "Statistiques"
#: extensions/stats/main.py:66 extensions/stats/main.py:95
msgid "No Domain defined"
msgstr "Aucun domaine défini."
#: extensions/stats/templates/index.html:62
msgid "Graph type"
msgstr ""
#: extensions/stats/templates/index.html:63
msgid "Domain name"
msgstr "Nom du domaine"
#: main/forms.py:17
msgid "Old password"
msgstr "Ancien mot de passe"
@@ -459,7 +539,6 @@ msgid "Permissions"
msgstr ""
#: templates/main/confirm.html:26
#, fuzzy
msgid "Do not delete mailbox directory"
msgstr "Ne pas supprimer le répertoire de la boite aux lettres"
+7 -3
View File
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-04-17 11:30+0200\n"
"POT-Creation-Date: 2009-10-30 11:11+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -20,14 +20,18 @@ msgstr ""
msgid "Delete this domain?"
msgstr "Supprimer ce domaine?"
#: static/js/domains.js:21
#: static/js/domains.js:22
msgid "Delete this mailbox?"
msgstr "Supprimer cette boite aux lettres?"
#: static/js/domains.js:27
#: static/js/domains.js:36
msgid "Delete this alias?"
msgstr "Supprimer cet alias?"
#: static/js/form.js:55
msgid "Help"
msgstr "Aide"
#: static/js/settings.js:9
msgid "Remove this permission?"
msgstr "Supprimer cette permission?"
-1
View File
@@ -55,7 +55,6 @@ window.addEvent('domready', function() {
});
$('body').addEvent('submit', function(event) {
alert("newodm submit");
target = event.target;
if (target.get('tag') == 'form') {
name = target.get('name');
+8
View File
@@ -50,4 +50,12 @@ window.addEvent("domready", function() {
if ($("chpwdform"))
$("chpwdform").addEvent("submit", chpassword_submit);
$$("input[type!=submit]", "select").each(function(elt) {
elt.store("tip:title", gettext("Help"));
if ($(elt.name + "_helptext")) {
elt.store("tip:text", $(elt.name + "_helptext").get("html"));
}
});
var tip = new Tips($$("input[type!=submit]", "select"));
});
+202 -5
View File
@@ -23,8 +23,8 @@ provides: [MooTools.More]
*/
MooTools.More = {
'version': '1.2.4.2dev',
'build': '%build%'
'version': '1.2.4.2',
'build': 'bd5a93c0913cce25917c48cbdacde568e15e02ef'
};
/*
@@ -53,7 +53,8 @@ Fx.Slide = new Class({
Extends: Fx,
options: {
mode: 'vertical'
mode: 'vertical',
hideOverflow: true
},
initialize: function(element, options){
@@ -64,9 +65,10 @@ Fx.Slide = new Class({
this.element = this.subject = document.id(element);
this.parent(options);
var wrapper = this.element.retrieve('wrapper');
var styles = this.element.getStyles('margin', 'position', 'overflow');
if (this.options.hideOverflow) styles = $extend(styles, {overflow: 'hidden'});
this.wrapper = wrapper || new Element('div', {
styles: $extend(this.element.getStyles('margin', 'position'), {overflow: 'hidden'})
/*styles: this.element.getStyles('margin', 'position', 'overflow', 'hidden')*/
styles: styles
}).wraps(this.element);
this.element.store('wrapper', this.wrapper).setStyle('margin', 0);
this.now = [];
@@ -178,3 +180,198 @@ Element.implement({
}
});
/*
---
script: Tips.js
description: Class for creating nice tips that follow the mouse cursor when hovering an element.
license: MIT-style license
authors:
- Valerio Proietti
- Christoph Pojer
requires:
- core:1.2.4/Options
- core:1.2.4/Events
- core:1.2.4/Element.Event
- core:1.2.4/Element.Style
- core:1.2.4/Element.Dimensions
- /MooTools.More
provides: [Tips]
...
*/
(function(){
var read = function(option, element){
return (option) ? ($type(option) == 'function' ? option(element) : element.get(option)) : '';
};
this.Tips = new Class({
Implements: [Events, Options],
options: {
/*
onAttach: $empty(element),
onDetach: $empty(element),
*/
onShow: function(){
this.tip.setStyle('display', 'block');
},
onHide: function(){
this.tip.setStyle('display', 'none');
},
title: 'title',
text: function(element){
return element.get('rel') || element.get('href');
},
showDelay: 100,
hideDelay: 100,
className: 'tip-wrap',
offset: {x: 16, y: 16},
fixed: false
},
initialize: function(){
var params = Array.link(arguments, {options: Object.type, elements: $defined});
this.setOptions(params.options);
document.id(this);
if (params.elements) this.attach(params.elements);
},
toElement: function(){
if (this.tip) return this.tip;
this.container = new Element('div', {'class': 'tip'});
return this.tip = new Element('div', {
'class': this.options.className,
styles: {
position: 'absolute',
top: 0,
left: 0,
visibility: 'hidden',
display: 'none'
}
}).adopt(
new Element('div', {'class': 'tip-top'}),
this.container,
new Element('div', {'class': 'tip-bottom'})
).inject(document.body);
},
attach: function(elements){
$$(elements).each(function(element){
var title = read(this.options.title, element),
text = read(this.options.text, element);
element.erase('title').store('tip:native', title).retrieve('tip:title', title);
element.retrieve('tip:text', text);
this.fireEvent('attach', [element]);
var events = ['enter', 'leave'];
if (!this.options.fixed) events.push('move');
events.each(function(value){
var event = element.retrieve('tip:' + value);
if (!event) event = this['element' + value.capitalize()].bindWithEvent(this, element);
element.store('tip:' + value, event).addEvent('mouse' + value, event);
}, this);
element.addEvent('mouseout', this.hide.bind(this, element)); // firefox doesn't handle mouseleave correct
}, this);
return this;
},
detach: function(elements){
$$(elements).each(function(element){
['enter', 'leave', 'move'].each(function(value){
element.removeEvent('mouse' + value, element.retrieve('tip:' + value)).eliminate('tip:' + value);
});
this.fireEvent('detach', [element]);
if (this.options.title == 'title'){ // This is necessary to check if we can revert the title
var original = element.retrieve('tip:native');
if (original) element.set('title', original);
}
}, this);
return this;
},
elementEnter: function(event, element){
this.container.empty();
['title', 'text'].each(function(value){
var content = element.retrieve('tip:' + value);
if (content) this.fill(new Element('div', {'class': 'tip-' + value}).inject(this.container), content);
}, this);
$clear(this.timer);
this.timer = this.show.delay(this.options.showDelay, this, [element, event]);
},
elementLeave: function(event, element){
this.tip.setStyle('visibility', 'hidden');
$clear(this.timer);
this.timer = this.hide.delay(this.options.hideDelay, this, element);
this.fireForParent(event, element);
},
fireForParent: function(event, element){
var element = $(element);
if (!element) return;
parentNode = element.getParent();
if (parentNode == document.body) return;
if (parentNode.retrieve('tip:enter')) parentNode.fireEvent('mouseenter', event);
else this.fireForParent(event, parentNode);
},
elementMove: function(event, element) {
this.position(event);
},
position: function(event){
if (this.tip.getStyle('display') != 'block') return;
var size = window.getSize(), scroll = window.getScroll(),
tip = {x: this.tip.offsetWidth, y: this.tip.offsetHeight},
props = {x: 'left', y: 'top'},
obj = {};
for (var z in props){
obj[props[z]] = event.page[z] + this.options.offset[z];
if ((obj[props[z]] + tip[z] - scroll[z]) > size[z]) obj[props[z]] = event.page[z] - this.options.offset[z] - tip[z];
}
this.tip.setStyles(obj);
this.tip.setStyle('visibility', 'visible');
},
fill: function(element, contents){
if(typeof contents == 'string') element.set('html', contents);
else element.adopt(contents);
},
show: function(element, event) {
this.fireEvent('show', [this.tip, element]);
this.position((this.options.fixed) ? {page: element.getPosition()} : event);
},
hide: function(element){
this.fireEvent('hide', [this.tip, element]);
}
});
})();
+5
View File
@@ -337,3 +337,8 @@ body {
float: left;
font-style: italic;
}
#notifybox {
margin: 20px;
font-weight: bold;
}
+25 -1
View File
@@ -101,4 +101,28 @@ input:hover {
#dlg-buttons input {
width: 90px;
}
}
/* Mootools tooltips */
.tip {
color: #fff;
width: 139px;
z-index: 13000;
border: 1px solid #cccccc;
}
.tip-title {
font-weight: bold;
font-size: 11px;
margin: 0;
color: #9FD4FF;
padding: 8px 8px 4px;
background: #eee;
}
.tip-text {
font-size: 11px;
padding: 4px 8px 8px;
background: #eee;
color: black;
}
+1 -1
View File
@@ -1,4 +1,4 @@
{% extends "admin/layout_simple.html" %}
{% extends "layout_simple.html" %}
{% load i18n %}
{% block html_head %}
<script src="/static/js/form.js" type="text/javascript"></script>
+1 -1
View File
@@ -1,4 +1,4 @@
{% extends "admin/layout_simple.html" %}
{% extends "layout_simple.html" %}
{% block html_head %}
<script src="/static/js/form.js" type="text/javascript"></script>
{% endblock %}
+1 -1
View File
@@ -1,4 +1,4 @@
{% extends "admin/layout_simple.html" %}
{% extends "layout_simple.html" %}
{% block html_head %}
<script src="/static/js/form.js" type="text/javascript"></script>
{% endblock %}
+2 -2
View File
@@ -1,10 +1,10 @@
{% extends "admin/layout_simple.html" %}
{% extends "layout_simple.html" %}
{% load i18n %}
{% block html_head %}
<script src="/static/js/form.js" type="text/javascript"></script>
{% endblock %}
{% block content %}
<div class="title"><h1>Mailbox {{ mbox.name }}</h1></div>
<div class="title"><h1>{% trans "Mailbox" %} {{ mbox.name }}</h1></div>
{% if error %}<div class="error">{{ error }}</div>{% endif %}
{% url admin.views.editmailbox mbox.domain_id mbox.id as box_url %}
+2
View File
@@ -1,5 +1,7 @@
{% for field in form %}
<div class="row">
{% if field.help_text %}
<div id="{{ field.name }}_helptext" style="display:none">{{ field.help_text}}</div>{% endif %}
{{ field.label_tag }} {{ field }} {% ifequal noerrors False %}{{ field.errors }}{% endifequal %}
</div>
{% endfor %}
-18
View File
@@ -1,18 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="/static/stylesheets/SqueezeBox.css" />
<link rel="stylesheet" type="text/css" href="/static/stylesheets/box.css" />
<script src="/static/js/mootools.js" type="text/javascript"></script>
<script src="/static/js/SqueezeBox.js" type="text/javascript"></script>
{%block html_head %}{% endblock %}
</head>
<body>
<div id="content">
{%block content %}{% endblock %}
</div>
</body>
</html>
+1 -1
View File
@@ -1,4 +1,4 @@
{% extends "admin/layout_simple.html" %}
{% extends "layout_simple.html" %}
{% load i18n %}
{% block html_head %}
<script src="/static/js/form.js" type="text/javascript"></script>
+1 -1
View File
@@ -1,4 +1,4 @@
{% extends "admin/layout_simple.html" %}
{% extends "layout_simple.html" %}
{% load i18n %}
{% block html_head %}
<script src="/static/js/form.js" type="text/javascript"></script>
+3
View File
@@ -6,7 +6,10 @@
<link rel="stylesheet" type="text/css" href="/static/stylesheets/SqueezeBox.css" />
<link rel="stylesheet" type="text/css" href="/static/stylesheets/box.css" />
<script src="/static/js/mootools.js" type="text/javascript"></script>
<script src="/static/js/mootools-more.js" type="text/javascript"></script>
<script src="/static/js/SqueezeBox.js" type="text/javascript"></script>
{% url django.views.i18n.javascript_catalog as catalog_url %}
<script type="text/javascript" src="/jsi18n/"></script>
{%block html_head %}{% endblock %}
</head>