add new features: create mailto and picture version 0.0.2
authorJens Kasten <jens@kasten-edv.de>
Tue, 24 Jul 2012 16:58:48 +0200
changeset 34 7eca7b9649ea
parent 31 de2f0d4d6e25 (current diff)
parent 33 061ed7f07787 (diff)
child 35 04134814b775
add new features: create mailto and picture
--- a/cmsplugin_nextlink/admin.py	Wed Jul 04 18:50:57 2012 +0200
+++ b/cmsplugin_nextlink/admin.py	Tue Jul 24 16:58:48 2012 +0200
@@ -2,33 +2,51 @@
 
 from django.contrib import admin
 from django.utils.translation import ugettext_lazy as _
-
 #from cms.admin.placeholderadmin import PlaceholderAdmin
 
 from cmsplugin_nextlink.models import NextLink
-from cmsplugin_nextlink.utils import is_link_expired, set_default_link_expired_date
+from cmsplugin_nextlink.forms import NextLinkForm
+from cmsplugin_nextlink.utils import (is_link_expired, 
+    set_default_link_expired_date)
 
 
 def make_link_expired(modeladmin, request, queryset):
     queryset.update(link_expired=datetime.datetime.now())
 make_link_expired.short_description = _("Mark selected next links as expired")
 
-
 def make_link_active(modeladmin, request, queryset):
     queryset.update(link_expired=set_default_link_expired_date())
 make_link_active.short_description = _("Mark selected next links as active")
 
-
 class NextLinkAdmin(admin.ModelAdmin):
+    form = NextLinkForm
     list_display = ['id','name', 'link_created', 'link_expired', 'description']
-    fieldsets = [
-        (None, {"fields": ["name", "protocol", "url", "title"]}),
-        (_("Link information"), {"fields": ["access_key"], "classes": ["collapse"]}),
-        (_("Image setup"), {"fields": ["image", "alt_attribute"], 'classes': ['collapse']}),
-        (_("Expired information"), {"fields": ["link_expired"], "classes": ["collapse"]}),
-        (_("Description interanl"), {"fields": ["description"], "classes": ["collapse"]}),
-    ]
     actions = [make_link_expired, make_link_active]
 
+    fieldsets = (
+        (None, {"fields": 
+            ["name", 
+             "description", 
+             "protocol"]}),
+        (_("Protocol options: Use only only of this fields below:"), {"fields": 
+            ["link_url", 
+             "mailto_address", 
+             "image"]}),
+        (_("Standard optional attributes"), {"fields": 
+            ["link_attr_title", 
+             "image_attr_alt", 
+             "link_attr_accesskey", 
+             "link_attr_tabindex",
+             "mailto_subject"], "classes": ["collapse"]}),
+        (_("Optional attribues"), {"fields": 
+            ["link_attr_class", 
+             "link_attr_id", 
+             "link_attr_dir", 
+             "link_attr_charset", 
+             "link_attr_style", 
+             "link_attr_name"], "classes": ["collapse"]}),
+        (_("Expired information"), {"fields": 
+            ["link_expired"], "classes": ["collapse"]}),
+    )
 
 admin.site.register(NextLink, NextLinkAdmin)
--- a/cmsplugin_nextlink/cms_plugins.py	Wed Jul 04 18:50:57 2012 +0200
+++ b/cmsplugin_nextlink/cms_plugins.py	Tue Jul 24 16:58:48 2012 +0200
@@ -1,5 +1,4 @@
-import datetime
-
+from django.contrib import admin
 from django.utils.translation import ugettext_lazy as _
 from django.conf import settings
 
@@ -7,55 +6,66 @@
 from cms.plugin_base import CMSPluginBase
 
 from cmsplugin_nextlink.models import NextLink
+from cmsplugin_nextlink.forms import NextLinkForm
 from cmsplugin_nextlink.utils import is_link_expired
 
 
 class NextLinkPlugin(CMSPluginBase):
-   
-    model = NextLink
+    model = NextLink 
+    form = NextLinkForm
     name = _("NextLink")
     render_template = "cmsplugin_nextlink/nextlink_plugin.html"
     text_enabled = True
     fieldsets = [
-        (None, {"fields": ["name", "protocol", "url", "title"]}),
-        (_("Link information"), {"fields": ["access_key"], "classes": ["collapse"]}),
-        (_("Image setup"), {"fields": ["image", "alt_attribute"], 'classes': ['collapse']}),
-        (_("Expired information"), {"fields": ["link_expired"], "classes": ["collapse"]}),
-        (_("Description interanl"), {"fields": ["description"], "classes": ["collapse"]}),
+        (None, {"fields": 
+            ["name", 
+             "description", 
+             "protocol"]}),
+        (_("Protocol options"), {"fields": 
+            ["link_url", 
+             "mailto_address", 
+             "image"]}),
+        (_("Standard optional attributes"), {"fields": 
+            ["link_attr_title", 
+             "image_attr_alt", 
+             "link_attr_accesskey", 
+             "link_attr_tabindex",
+             "mailto_subject"], "classes": ["collapse"]}),
+        (_("Optional attribues"), {"fields": 
+            ["link_attr_class", 
+             "link_attr_id", 
+             "link_attr_dir", 
+             "link_attr_charset", 
+             "link_attr_style", 
+             "link_attr_name"], "classes": ["collapse"]}),
+        (_("Expired information"), {"fields": 
+            ["link_expired"], "classes": ["collapse"]}),
     ]
 
     def render(self, context, instance, placeholder):
         if "internal" in instance.nextlink.protocol:
-            if not instance.nextlink.url.startswith("/"):
-                url = "/" + instance.nextlink.url
+            if not instance.nextlink.link_url.startswith("/"):
+                url = "/" + instance.nextlink.link_url
             else:
-                url = instance.nextlink.url
-        else:
-            url = instance.nextlink.protocol + "://" + instance.nextlink.url
-        if len(instance.nextlink.title) > 0:
-            title = instance.nextlink.title
+                url = instance.nextlink.link_url
+        elif "mailto" in instance.nextlink.protocol:
+            url = "mailto:" + instance.nextlink.mailto_address + "?subject=" + instance.nextlink.mailto_subject
         else:
-            title = instance.nextlink.name 
-        if instance.nextlink.access_key:
-            access_key = instance.nextlink.access_key
+            url = instance.nextlink.link_url
+        if "picture" in instance.nextlink.protocol:
+            picture = True
         else:
-            access_key = False
-        if instance.nextlink.image:
-            image = instance.nextlink.image
-        else:
-            image = False
-        if instance.nextlink.alt_attribute:
-            alt = instance.nextlink.alt_attibute
-        else:
-            alt = instance.nextlink.name
+            picture = False
         context.update({
+            'picture': picture,
             'name': instance.nextlink.name,
             'url': url,
-            'title': title,
-            'access_key': access_key,
+            'title': instance.nextlink.link_attr_title,
+            'accesskey': instance.nextlink.link_attr_accesskey,
+            'tabindex': instance.nextlink.link_attr_tabindex,
             'link_expired': is_link_expired(instance.nextlink.link_expired),
-            'image': image,
-            'alt': alt,
+            'image': instance.nextlink.image,
+            'alt': instance.nextlink.image_attr_alt,
             'media_url': settings.MEDIA_URL,
             'object': instance,
             'placeholder': placeholder,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmsplugin_nextlink/forms.py	Tue Jul 24 16:58:48 2012 +0200
@@ -0,0 +1,70 @@
+from django import forms
+from django.db import models
+from django.forms.models import inlineformset_factory
+from django.utils.translation import ugettext_lazy as _
+from django.core.validators import URLValidator, EmailValidator, validate_email
+from django.core.exceptions import ValidationError 
+
+from cmsplugin_nextlink.models import NextLink
+from cmsplugin_nextlink.utils import is_integer
+
+
+class NextLinkForm(forms.ModelForm):
+
+    class Meta:
+        model = NextLink
+
+    def clean(self):
+        cleaned_data = super(NextLinkForm, self).clean()
+        protocol = cleaned_data.get("protocol")
+        # check protocol depencies
+        if "mailto" in protocol:
+            if cleaned_data.get("link_url"):
+                msg = _(u"URL is not allowed in combination with mailto protocol.")
+                self._errors["link_url"] = self.error_class([msg])
+                del cleaned_data["link_url"]
+            if not cleaned_data.get("mailto_address"):
+                msg = _(u"Mailto address is missing.")
+                self._errors["mailto_address"] = self.error_class([msg])
+            if not cleaned_data.get("mailto_subject"):
+                msg = _(u"Mailto subject is missing.")
+                self._errors["mailto_subject"] = self.error_class([msg])
+            try:
+                #validate_email = EmailValidator()
+                validate_email(str(cleaned_data["mailto_address"]))
+            except ValidationError, e:
+                self._errors["mailto_address"] = self.error_class([str("%s" % e)])
+                del cleaned_data["mailto_address"]
+        elif "picture" in protocol:
+            if cleaned_data.get("link_url"):
+                msg = _(u"URL is not allowed in combination with picture protocol.")
+                self._errors["link_url"] = self.error_class([msg])
+                del cleaned_data["link_url"]
+            if cleaned_data.get("mailto_address"):
+                msg = _(u"Mailto address is not allowed in combination with picture protocol.")
+                self._errors["mailto_address"] = self.error_class([msg])
+                del cleaned_data["mailto_address"]
+            if not cleaned_data.get("image"):
+                msg = _(u"Image is missing.")
+                self._errors["image"] = self.error_class([msg])
+        else:
+            if cleaned_data.get("mailto_address"):
+                msg = _(u"Mailto address is not allowed in combination with internal or external protocol.")
+                self._errors["mailto_address"] = self.error_class([msg])
+                del cleaned_data["mailto_address"]
+            if cleaned_data.get("mailto_subject"):
+                msg = _(u"Maitlo subject is not allowd in combination with internal or external protocol.")
+                self._errors["mailto_subject"] = self.error_class([msg])
+                del cleaned_data["mailto_subject"]
+            if not cleaned_data.get("link_url"):
+                msg = _(u"URL is missing.")
+                self._errors["link_url"] = self.error_class([msg])
+            if "external" in protocol:
+                try:
+                    validate_url = URLValidator(verify_exists=False)
+                    validate_url(str(cleaned_data["link_url"]))
+                except ValidationError, e:
+                    msg = _(u"The give url has not a valid format.")
+                    self._errors["link_url"] = self.error_class([msg])
+                    del cleaned_data["link_url"]
+        return cleaned_data 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmsplugin_nextlink/migrations/0005_auto__del_field_nextlink_access_key__del_field_nextlink_title__del_fie.py	Tue Jul 24 16:58:48 2012 +0200
@@ -0,0 +1,169 @@
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        
+        # Deleting field 'NextLink.access_key'
+        db.delete_column('cmsplugin_nextlink', 'access_key')
+
+        # Deleting field 'NextLink.title'
+        db.delete_column('cmsplugin_nextlink', 'title')
+
+        # Deleting field 'NextLink.url'
+        db.delete_column('cmsplugin_nextlink', 'url')
+
+        # Deleting field 'NextLink.alt_attribute'
+        db.delete_column('cmsplugin_nextlink', 'alt_attribute')
+
+        # Adding field 'NextLink.link_url'
+        db.add_column('cmsplugin_nextlink', 'link_url', self.gf('django.db.models.fields.CharField')(max_length=256, null=True, blank=True), keep_default=False)
+
+        # Adding field 'NextLink.mailto_address'
+        db.add_column('cmsplugin_nextlink', 'mailto_address', self.gf('django.db.models.fields.CharField')(max_length=256, null=True, blank=True), keep_default=False)
+
+        # Adding field 'NextLink.mailto_subject'
+        db.add_column('cmsplugin_nextlink', 'mailto_subject', self.gf('django.db.models.fields.CharField')(max_length=256, null=True, blank=True), keep_default=False)
+
+        # Adding field 'NextLink.link_attr_title'
+        db.add_column('cmsplugin_nextlink', 'link_attr_title', self.gf('django.db.models.fields.CharField')(max_length=256, null=True, blank=True), keep_default=False)
+
+        # Adding field 'NextLink.link_attr_accesskey'
+        db.add_column('cmsplugin_nextlink', 'link_attr_accesskey', self.gf('django.db.models.fields.CharField')(max_length=3, null=True, blank=True), keep_default=False)
+
+        # Adding field 'NextLink.link_attr_tabindex'
+        db.add_column('cmsplugin_nextlink', 'link_attr_tabindex', self.gf('django.db.models.fields.PositiveIntegerField')(null=True, blank=True), keep_default=False)
+
+        # Adding field 'NextLink.link_attr_class'
+        db.add_column('cmsplugin_nextlink', 'link_attr_class', self.gf('django.db.models.fields.CharField')(max_length=256, null=True, blank=True), keep_default=False)
+
+        # Adding field 'NextLink.link_attr_id'
+        db.add_column('cmsplugin_nextlink', 'link_attr_id', self.gf('django.db.models.fields.CharField')(max_length=256, null=True, blank=True), keep_default=False)
+
+        # Adding field 'NextLink.link_attr_dir'
+        db.add_column('cmsplugin_nextlink', 'link_attr_dir', self.gf('django.db.models.fields.CharField')(default='rtl', max_length=256, null=True), keep_default=False)
+
+        # Adding field 'NextLink.link_attr_style'
+        db.add_column('cmsplugin_nextlink', 'link_attr_style', self.gf('django.db.models.fields.CharField')(max_length=256, null=True, blank=True), keep_default=False)
+
+        # Adding field 'NextLink.link_attr_name'
+        db.add_column('cmsplugin_nextlink', 'link_attr_name', self.gf('django.db.models.fields.CharField')(max_length=256, null=True, blank=True), keep_default=False)
+
+        # Adding field 'NextLink.link_attr_charset'
+        db.add_column('cmsplugin_nextlink', 'link_attr_charset', self.gf('django.db.models.fields.CharField')(max_length=256, null=True, blank=True), keep_default=False)
+
+        # Adding field 'NextLink.image_attr_alt'
+        db.add_column('cmsplugin_nextlink', 'image_attr_alt', self.gf('django.db.models.fields.CharField')(max_length=256, null=True, blank=True), keep_default=False)
+
+        # Changing field 'NextLink.protocol'
+        db.alter_column('cmsplugin_nextlink', 'protocol', self.gf('django.db.models.fields.CharField')(max_length=8))
+
+
+    def backwards(self, orm):
+        
+        # Adding field 'NextLink.access_key'
+        db.add_column('cmsplugin_nextlink', 'access_key', self.gf('django.db.models.fields.CharField')(max_length=1, null=True, blank=True), keep_default=False)
+
+        # Adding field 'NextLink.title'
+        db.add_column('cmsplugin_nextlink', 'title', self.gf('django.db.models.fields.CharField')(max_length=256, null=True, blank=True), keep_default=False)
+
+        # Adding field 'NextLink.url'
+        db.add_column('cmsplugin_nextlink', 'url', self.gf('django.db.models.fields.CharField')(default=False, max_length=256), keep_default=False)
+
+        # Adding field 'NextLink.alt_attribute'
+        db.add_column('cmsplugin_nextlink', 'alt_attribute', self.gf('django.db.models.fields.CharField')(max_length=256, null=True, blank=True), keep_default=False)
+
+        # Deleting field 'NextLink.link_url'
+        db.delete_column('cmsplugin_nextlink', 'link_url')
+
+        # Deleting field 'NextLink.mailto_address'
+        db.delete_column('cmsplugin_nextlink', 'mailto_address')
+
+        # Deleting field 'NextLink.mailto_subject'
+        db.delete_column('cmsplugin_nextlink', 'mailto_subject')
+
+        # Deleting field 'NextLink.link_attr_title'
+        db.delete_column('cmsplugin_nextlink', 'link_attr_title')
+
+        # Deleting field 'NextLink.link_attr_accesskey'
+        db.delete_column('cmsplugin_nextlink', 'link_attr_accesskey')
+
+        # Deleting field 'NextLink.link_attr_tabindex'
+        db.delete_column('cmsplugin_nextlink', 'link_attr_tabindex')
+
+        # Deleting field 'NextLink.link_attr_class'
+        db.delete_column('cmsplugin_nextlink', 'link_attr_class')
+
+        # Deleting field 'NextLink.link_attr_id'
+        db.delete_column('cmsplugin_nextlink', 'link_attr_id')
+
+        # Deleting field 'NextLink.link_attr_dir'
+        db.delete_column('cmsplugin_nextlink', 'link_attr_dir')
+
+        # Deleting field 'NextLink.link_attr_style'
+        db.delete_column('cmsplugin_nextlink', 'link_attr_style')
+
+        # Deleting field 'NextLink.link_attr_name'
+        db.delete_column('cmsplugin_nextlink', 'link_attr_name')
+
+        # Deleting field 'NextLink.link_attr_charset'
+        db.delete_column('cmsplugin_nextlink', 'link_attr_charset')
+
+        # Deleting field 'NextLink.image_attr_alt'
+        db.delete_column('cmsplugin_nextlink', 'image_attr_alt')
+
+        # Changing field 'NextLink.protocol'
+        db.alter_column('cmsplugin_nextlink', 'protocol', self.gf('django.db.models.fields.CharField')(max_length=8, null=True))
+
+
+    models = {
+        'cms.cmsplugin': {
+            'Meta': {'object_name': 'CMSPlugin'},
+            'creation_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'language': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}),
+            'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.CMSPlugin']", 'null': 'True', 'blank': 'True'}),
+            'placeholder': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['cms.Placeholder']", 'null': 'True'}),
+            'plugin_type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
+            'position': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+            'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
+        },
+        'cms.placeholder': {
+            'Meta': {'object_name': 'Placeholder'},
+            'default_width': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'slot': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'})
+        },
+        'cmsplugin_nextlink.nextlink': {
+            'Meta': {'object_name': 'NextLink', 'db_table': "'cmsplugin_nextlink'", '_ormbases': ['cms.CMSPlugin']},
+            'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'}),
+            'description': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
+            'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+            'image_attr_alt': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
+            'link_attr_accesskey': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True', 'blank': 'True'}),
+            'link_attr_charset': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
+            'link_attr_class': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
+            'link_attr_dir': ('django.db.models.fields.CharField', [], {'default': "'rtl'", 'max_length': '256', 'null': 'True'}),
+            'link_attr_id': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
+            'link_attr_name': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
+            'link_attr_style': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
+            'link_attr_tabindex': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'link_attr_title': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
+            'link_created': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'link_expired': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(3011, 11, 25, 16, 48, 21, 79764)', 'blank': 'True'}),
+            'link_url': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
+            'mailto_address': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
+            'mailto_subject': ('django.db.models.fields.CharField', [], {'max_length': '256', 'null': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
+            'protocol': ('django.db.models.fields.CharField', [], {'default': "'internal'", 'max_length': '8'})
+        }
+    }
+
+    complete_apps = ['cmsplugin_nextlink']
--- a/cmsplugin_nextlink/models.py	Wed Jul 04 18:50:57 2012 +0200
+++ b/cmsplugin_nextlink/models.py	Tue Jul 24 16:58:48 2012 +0200
@@ -2,50 +2,96 @@
 
 from django.db import models
 from django.utils.translation import ugettext_lazy as _
-from django.conf import settings
 
 from cms.models import CMSPlugin
 
 from cmsplugin_nextlink.utils import PROTOCOLS, set_default_link_expired_date
-from cmsplugin_nextlink.validator import validator_url
+from cmsplugin_nextlink.validator import validator_uri
 
 
 class NextLink(CMSPlugin):
-    """Define the attribute for database.
-    FIXME: think about imagefield if the link is klickable with an image
-    """
-    name = models.CharField(_("Name"), max_length=256,
+    """Define the attribute for database."""
+    choices_tabindex = [(0, "0"), (1, "1"), (2, "2"), (3, "3"), (4, "4"), 
+        (5, "5"), (6, "6"), (7, "7"), (8, "8"), (9, "9")]
+    choices_dir = [("rtl", "rtl"), ("ltr", "ltr")]
+    name = models.CharField(_("Name"), 
+        max_length=256,
         help_text=_("The name of the link for displaying on the webpage."))
-    protocol = models.CharField(_("Protocol"), max_length=8, choices=PROTOCOLS, 
-        default="internal", null=True,
-        help_text=_("Choose a protocol or use internal as default."))
-    url = models.CharField(_("Url"), max_length=256, 
-        help_text=_("Enter the url, if it for internal use then just the path. "
+    description = models.CharField(_("description"),
+        max_length=256, null=True, blank=True,
+        help_text = _("Optional, give a short description for the admin page."))
+    protocol = models.CharField(_("Protocol"), 
+        max_length=8, 
+        choices=PROTOCOLS, default="internal",
+        help_text=_("Choose a protocol, targets are 'internal' or 'external' "
+                    "for links or 'mailto' to add this a link target "
+                    "or 'picture' to display an image only."))
+    link_url = models.CharField(_("URL"), 
+        max_length=256, null=True, blank=True, 
+        help_text=_("Enter the URL, if it for internal use then just the path. "
                     "Otherwise use valid URL."))
-    title = models.CharField(_("Title"), max_length=256, null=True, blank=True,
-        help_text=_("Optional set a title for the link name, if empty the name is used."))
-    access_key = models.CharField(_("Access key"), max_length=1, null=True, blank=True,
-        help_text=_("Optional set an accesskey. For example letter a for keystroke 'a'."))
-    link_created = models.DateTimeField(_('link created'), blank=True,
-        auto_now=True,
-        help_text=_("Set the date of creation."))
-    link_expired = models.DateTimeField(_('link expired'), blank=True, 
-        default=set_default_link_expired_date(), 
-        help_text=_("Set the date of expired, if is set and date is equal the link "
-                  "is not working anymore."))
+    mailto_address = models.CharField(_("Mailto"),
+        max_length=256, null=True, blank=True,
+        help_text=_("Fully qualified email address."))
+    mailto_subject = models.CharField(_("mailto subject"),
+        max_length=256, null=True, blank=True,
+        help_text=_("Optional, set an subject for mailto."))
+    link_attr_title = models.CharField(_("Attribute title"), 
+        max_length=256, null=True, blank=True,
+        help_text=_("Optional, specifies extra information about an element "
+                    "set a title for the link name, if empty the name is used."))
+    link_attr_accesskey = models.CharField(_("Attribute accesskey"), 
+        max_length=3, null=True, blank=True,
+        help_text=_("Optional, specifies a keyboard shortcut to access an element."))
+    link_attr_tabindex = models.PositiveIntegerField(_("Attribute tabindex"), 
+        null=True, blank=True,
+        choices=choices_tabindex,
+        help_text = _("Optional, specifies the tab order of an element."))
+    link_attr_class = models.CharField(_("Attribute class"), 
+        max_length=256, null=True, blank=True,
+        help_text=_("Optional, specifies a classname for an element."))
+    link_attr_id = models.CharField(_("Attribute id"), 
+        max_length=256, null=True, blank=True,
+        help_text=_("Optional, specifies a unique id for an element set a link id."))
+    link_attr_dir = models.CharField(_("Attribute dir"), 
+        max_length=256, null=True, choices=choices_dir, default="rtl",
+        help_text=_("Optional, specifies the text direction for the "
+                    "content in an element."))
+    link_attr_charset = models.CharField(_("Attribute charset"), 
+        max_length=256, null=True, blank=True,
+        help_text=_("Optional, specifies the character encoding of the "
+                    "resource designated by the link."))
+    link_attr_style = models.CharField(_("Attribute style"),
+        max_length=256, null=True, blank=True,
+        help_text=_("Optional, specifies an inline style for an element."))
+    link_attr_name = models.CharField(_("Attribute name"),
+        max_length=256, null=True, blank=True,
+        help_text=_("Optional, specifies the name of an anchor."))
+    link_attr_charset = models.CharField(_("Attribute charset"),
+        max_length=256, null=True, blank=True,
+        help_text=_("Optional, specifies the character-set of a linked document."))
+    link_created = models.DateTimeField(_('link created'), 
+        blank=True, auto_now=True)
+    link_expired = models.DateTimeField(_('link expired'), 
+        blank=True, default=set_default_link_expired_date(), 
+        help_text=_("Set the date of expired, if is set and date is equal "
+                    "the link is not working anymore."))
     image = models.ImageField(_("Image"), upload_to="nextlink_archive", 
         null=True, blank=True,
-        help_text = _("Choose an image to make the link clickable. If you want only display an image set the expired time to now."))
-    alt_attribute = models.CharField(_("alt"), null=True, blank=True,
-        max_length=256,
+        help_text = _("Choose an image to make the link clickable. "
+                      "If you want only display an image set the "
+                      "expired time to now."))
+    image_attr_alt = models.CharField(_("Attribute alt"), 
+        max_length=256, null=True, blank=True,
         help_text = _("Optional set an alt attibute for the image"))
-    description = models.CharField(_("description"), null=True, blank=True,
-        max_length=256,
-        help_text = _("Optional give a short description."))
     
-    def clean(self):
-        validator_url(self.protocol, self.url)
-
+    def save(self, *args, **kwargs):
+        if not self.link_attr_title:
+            self.link_attr_title = self.name
+        if self.image and not self.image_attr_alt:
+            self.image_attr_alt = self.name
+        super(NextLink, self).save()
+    
     def __unicode__(self):
         return self.name
 
--- a/cmsplugin_nextlink/templates/cmsplugin_nextlink/nextlink_plugin.html	Wed Jul 04 18:50:57 2012 +0200
+++ b/cmsplugin_nextlink/templates/cmsplugin_nextlink/nextlink_plugin.html	Tue Jul 24 16:58:48 2012 +0200
@@ -1,7 +1,12 @@
-{% if link_expired %}
-<span class="plugin_nextlink">{% if image %}<img src="{{ media_url }}{{ image }}" alt="{{ alt }}" title="{{ title }}" />{% else %}<s>{{ name }}</s>{% endif %}</span>
-{% else %}
-<span class="plugin_nextlink">
-<a href="{{ url }}" title="{{ title }}" {% if access_key %}accesskey="{{ access_key }}"{% endif %}>{% if image %}<img src="{{ media_url }}{{ image }}" alt="{{ alt }}"  title="{{ title }}" />{% else %}{{ name }}{% endif %}</a>
-</span>
+{% if picture %}
+    <span class="plugin_nextlink"><img src="{{ media_url }}{{ image }}"  alt="{{ alt }}" title="{{ title }}" /></span>
+{% else  %}
+    {% if link_expired %}
+        <span class="plugin_nextlink">{% if image %}<img src="{{ media_url }}{{ image }}" alt="{{ alt }}" title="{{ title }}" />{% else %}<s>{{ name }}</s>{% endif %}</span>
+    {% else %}
+        <span class="plugin_nextlink">
+        <a href="{{ url }}" title="{{ title }}" {% if accesskey %}accesskey="{{ accesskey }}"{% endif %} {% if tabindex %}tabindex="{{ tabindex }}"{% endif %}>
+            {% if image %}<img src="{{ media_url }}{{ image }}" alt="{{ alt }}"  title="{{ title }}" />{% else %}{{ name }}{% endif %}</a>
+        </span>
+    {% endif %}
 {% endif %}
--- a/cmsplugin_nextlink/utils.py	Wed Jul 04 18:50:57 2012 +0200
+++ b/cmsplugin_nextlink/utils.py	Tue Jul 24 16:58:48 2012 +0200
@@ -1,3 +1,4 @@
+import re
 import datetime
 
 from django.utils.translation import ugettext_lazy as _
@@ -5,9 +6,9 @@
 
 PROTOCOLS = (
     ("internal", _("internal")),
-    ("http", "http"),
-    ("https", "https"),
-    ("ftp", "ftp"),
+    ("external", _("external")),
+    ("mailto", _("mailto")),
+    ("picture", _("picture")),
 )
 
 def is_link_expired(link_expired):
@@ -29,3 +30,12 @@
     # maybe could be set up of a fix date
     date_in_the_future = datetime.datetime.now() + datetime.timedelta(days=365000)
     return date_in_the_future   
+
+def is_integer(integer_value):
+    """Pseudo interger testing."""
+    if not re.match(r"[0-9]+", integer_value):
+        return False
+    else:
+        return True
+
+   
--- a/cmsplugin_nextlink/validator.py	Wed Jul 04 18:50:57 2012 +0200
+++ b/cmsplugin_nextlink/validator.py	Tue Jul 24 16:58:48 2012 +0200
@@ -1,31 +1,35 @@
+import re
+
 from django.core.exceptions import ValidationError
-from django.core.validators import URLValidator
+from django.core.validators import URLValidator, EmailValidator
 from django.utils.translation import ugettext_lazy as _
 
 from cmsplugin_nextlink.utils import PROTOCOLS
 
 
-def validator_tab_index(value):
-    if value > 10:
-         raise ValidationError(_(u'You can only use a range from 0 to 9.'))
 
-def validator_url(which_protocol, url_to_validate):
+def validator_uri(which_protocol, uri_to_validate):
     """Check if the url does not have some protocol"""
-    validate_url = URLValidator(verify_exists=False)
-    if "internal" not in which_protocol:
-        url = which_protocol + "://" + url_to_validate
+    #raise RuntimeError(which_protocol, uri_to_validate[0])
+    if "mailto" in which_protocol:
+        return True
+    for protocol in PROTOCOLS:
+        if protocol[0] in uri_to_validate:
+            raise ValidationError(_(u'Wrong input for uri. Make sure that you don\'t use something like http:// in your url. [%s]' % uri_to_validate))
+    
+    validate_uri = URLValidator(verify_exists=False)
+    if ("internal" or "mailto") not in which_protocol:
+        uri = which_protocol + "://" + uri_to_validate
     else:
-        # use localhost as domain name
-        for protocol in PROTOCOLS:
-            if protocol[0] in url_to_validate:
-                raise ValidationError(_(u'Wrong input for url. Make sure that you don\'t use something like http:// in your url. [%s]' % url_to_validate))
-        if not url_to_validate.startswith("/"):
-            url = "http://localhost/" + url_to_validate
-        else:
-            url = "http://localhost" + url_to_validate
+        if "internal" in which_protocol:
+            # use localhost as domain name
+           if not uri_to_validate.startswith("/"):
+                uri = "http://localhost/" + uri_to_validate
+           else:
+                uri = "http://localhost" + uri_to_validate
     try:
-        validate_url(url)
+        validate_uri(uri)
     except ValidationError, e:
-        raise ValidationError(_(u'Wrong input for url. Make sure that you don\'t use something like http:// in your url. [%s]' % url))
+        raise ValidationError(_(u"%s [%s]" % (str(e), uri)))
     return True
-    
+
--- a/setup.py	Wed Jul 04 18:50:57 2012 +0200
+++ b/setup.py	Tue Jul 24 16:58:48 2012 +0200
@@ -2,8 +2,8 @@
 
 setup(
     name = "cmsplugin-nextlink",
-    version = "0.0.1.4",
-    description = "This is a theme plugin for django-cms 2.2",
+    version = "0.0.2",
+    description = "This is a link plugin for django-cms 2.2",
     long_description = open("README").read(),
     author = "Jens Kasten",
     author_email = "jens@kasten-edv.de",