mirror of
https://github.com/fergalmoran/dss.git
synced 2025-12-22 09:38:18 +00:00
Fixed comments (kinda)
This commit is contained in:
@@ -52,7 +52,7 @@ CACHE_ROOT = localsettings.CACHE_ROOT
|
||||
STATIC_URL = localsettings.STATIC_URL if hasattr(localsettings, 'STATIC_URL') else '/static/'
|
||||
|
||||
if DEBUG:
|
||||
MEDIA_URL = '/media/'
|
||||
MEDIA_URL = localsettings.MEDIA_URL if hasattr(localsettings, 'MEDIA_URL') else '/media/'
|
||||
else:
|
||||
MEDIA_URL = localsettings.MEDIA_URL if hasattr(localsettings, 'MEDIA_URL') else '/static/'
|
||||
|
||||
@@ -222,7 +222,9 @@ PIPELINE_CSS = {
|
||||
INTERNAL_IPS = ('127.0.0.1', '86.44.166.21', '192.168.1.111')
|
||||
|
||||
GOOGLE_ANALYTICS_CODE = localsettings.GOOGLE_ANALYTICS_CODE
|
||||
|
||||
TASTYPIE_DATETIME_FORMATTING = 'rfc-2822'
|
||||
TASTYPIE_ALLOW_MISSING_SLASH = True
|
||||
|
||||
SENDFILE_BACKEND = localsettings.SENDFILE_BACKEND
|
||||
SENDFILE_ROOT = os.path.join(MEDIA_ROOT, 'mixes')
|
||||
|
||||
@@ -2,9 +2,9 @@ from tastypie import fields
|
||||
from tastypie.authentication import Authentication
|
||||
from tastypie.authorization import Authorization
|
||||
from tastypie.exceptions import ImmediateHttpResponse
|
||||
from tastypie.http import HttpForbidden, HttpBadRequest
|
||||
from tastypie.http import HttpBadRequest, HttpMethodNotAllowed, HttpUnauthorized, HttpApplicationError, HttpNotImplemented
|
||||
from spa.api.v1.BackboneCompatibleResource import BackboneCompatibleResource
|
||||
from spa.models import Mix
|
||||
from spa.models import Mix, UserProfile
|
||||
from spa.models.comment import Comment
|
||||
|
||||
|
||||
@@ -21,32 +21,34 @@ class CommentResource(BackboneCompatibleResource):
|
||||
authentication = Authentication()
|
||||
always_return_data = True
|
||||
|
||||
def dehydrate(self, bundle):
|
||||
if bundle.obj.user is not None:
|
||||
bundle.data['avatar_image'] = bundle.obj.user.get_profile().get_avatar_image()
|
||||
bundle.data['user_url'] = bundle.obj.user.get_profile().get_absolute_url()
|
||||
bundle.data['user_name'] = bundle.obj.user.get_profile().get_nice_name()
|
||||
else:
|
||||
bundle.data['avatar_image'] = UserProfile.get_default_avatar_image()
|
||||
bundle.data['user_url'] = "/"
|
||||
bundle.data['user_name'] = "Anonymouse"
|
||||
return bundle
|
||||
|
||||
def obj_create(self, bundle, **kwargs):
|
||||
bundle.data['user'] = bundle.request.user
|
||||
del bundle.data['avatar_image']
|
||||
del bundle.data['user_url']
|
||||
del bundle.data['user_name']
|
||||
|
||||
try:
|
||||
if 'mix_id' in bundle.data:
|
||||
mix = Mix.objects.get(pk=bundle.data['mix_id'])
|
||||
mix = Mix.objects.get_by_id_or_slug(bundle.data['mix_id'])
|
||||
if mix is not None:
|
||||
return super(CommentResource, self).obj_create(bundle, user=bundle.request.user, mix=mix)
|
||||
if bundle.request.user.is_authenticated():
|
||||
return super(CommentResource, self).obj_create(bundle, user=bundle.request.user or None, mix=mix)
|
||||
else:
|
||||
return super(CommentResource, self).obj_create(bundle, mix=mix)
|
||||
else:
|
||||
return HttpBadRequest("Unable to find mix for supplied mix_id (candidate fields are slug & id).")
|
||||
|
||||
return HttpBadRequest("Missing mix_id field.")
|
||||
except ImmediateHttpResponse, e:
|
||||
self.logger.error("Error creating comment (%s)" % e.message)
|
||||
return HttpUnauthorized("Git tae fuck!")
|
||||
except Exception, e:
|
||||
self.logger.error("Error creating comment (%s)" % e.message)
|
||||
pass
|
||||
raise ImmediateHttpResponse(
|
||||
HttpBadRequest("Unable to hydrate comment from supplied data.")
|
||||
)
|
||||
|
||||
def obj_update(self, bundle, skip_errors=False, **kwargs):
|
||||
del bundle.data['avatar_image']
|
||||
del bundle.data['user_url']
|
||||
del bundle.data['user_name']
|
||||
return super(CommentResource, self).obj_update(bundle, bundle.request)
|
||||
|
||||
def dehydrate(self, bundle):
|
||||
bundle.data['avatar_image'] = bundle.obj.user.get_profile().get_small_profile_image()
|
||||
bundle.data['user_url'] = bundle.obj.user.get_absolute_url()
|
||||
bundle.data['user_name'] = bundle.obj.user.get_profile().get_nice_name() or bundle.obj.user.get_profile().display_name
|
||||
return bundle
|
||||
return HttpApplicationError("Unable to hydrate comment from supplied data.")
|
||||
|
||||
@@ -164,9 +164,6 @@ class MixResource(BackboneCompatibleResource):
|
||||
|
||||
return semi_filtered
|
||||
|
||||
def hydrate_favourited(self, bundle):
|
||||
return bundle
|
||||
|
||||
def dehydrate_mix_image(self, bundle):
|
||||
return bundle.obj.get_image_url(size="160x110")
|
||||
|
||||
|
||||
233
spa/migrations/0038_auto__chg_field_comment_user.py
Normal file
233
spa/migrations/0038_auto__chg_field_comment_user.py
Normal file
@@ -0,0 +1,233 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from south.utils import datetime_utils as datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Changing field 'Comment.user'
|
||||
db.alter_column(u'spa_comment', 'user_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True))
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Changing field 'Comment.user'
|
||||
db.alter_column(u'spa_comment', 'user_id', self.gf('django.db.models.fields.related.ForeignKey')(default=-1, to=orm['auth.User']))
|
||||
|
||||
models = {
|
||||
u'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
u'auth.permission': {
|
||||
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
u'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
u'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'spa._lookup': {
|
||||
'Meta': {'object_name': '_Lookup'},
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'spa.activity': {
|
||||
'Meta': {'object_name': 'Activity'},
|
||||
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'spa.activitydownload': {
|
||||
'Meta': {'object_name': 'ActivityDownload', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_downloads'", 'to': "orm['spa.Mix']"})
|
||||
},
|
||||
'spa.activityfavourite': {
|
||||
'Meta': {'object_name': 'ActivityFavourite', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_favourites'", 'to': "orm['spa.Mix']"})
|
||||
},
|
||||
'spa.activityfollow': {
|
||||
'Meta': {'object_name': 'ActivityFollow', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_follow'", 'to': "orm['spa.UserProfile']"})
|
||||
},
|
||||
'spa.activitylike': {
|
||||
'Meta': {'object_name': 'ActivityLike', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_likes'", 'to': "orm['spa.Mix']"})
|
||||
},
|
||||
'spa.activityplay': {
|
||||
'Meta': {'object_name': 'ActivityPlay', '_ormbases': ['spa.Activity']},
|
||||
u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_plays'", 'to': "orm['spa.Mix']"})
|
||||
},
|
||||
'spa.chatmessage': {
|
||||
'Meta': {'object_name': 'ChatMessage'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'message': ('django.db.models.fields.TextField', [], {}),
|
||||
'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'chat_messages'", 'null': 'True', 'to': "orm['spa.UserProfile']"})
|
||||
},
|
||||
'spa.comment': {
|
||||
'Meta': {'object_name': 'Comment'},
|
||||
'comment': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
|
||||
'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}),
|
||||
'time_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'spa.event': {
|
||||
'Meta': {'object_name': 'Event'},
|
||||
'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}),
|
||||
'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 11, 27, 0, 0)'}),
|
||||
'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 11, 27, 0, 0)'}),
|
||||
'event_description': ('tinymce.models.HTMLField', [], {}),
|
||||
'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}),
|
||||
'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 11, 27, 0, 0)'}),
|
||||
'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
|
||||
'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'spa.genre': {
|
||||
'Meta': {'object_name': 'Genre'},
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
|
||||
},
|
||||
'spa.label': {
|
||||
'Meta': {'object_name': 'Label'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'spa.mix': {
|
||||
'Meta': {'object_name': 'Mix'},
|
||||
'description': ('django.db.models.fields.TextField', [], {}),
|
||||
'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'favourites': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'favourites'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}),
|
||||
'genres': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Genre']", 'symmetrical': 'False'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_featured': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'likes': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'likes'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}),
|
||||
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}),
|
||||
'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '1024', 'blank': 'True'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}),
|
||||
'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}),
|
||||
'upload_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 11, 27, 0, 0)'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'mixes'", 'to': "orm['spa.UserProfile']"}),
|
||||
'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
|
||||
},
|
||||
'spa.notification': {
|
||||
'Meta': {'object_name': 'Notification'},
|
||||
'accepted_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||
'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
|
||||
'from_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notifications'", 'null': 'True', 'to': "orm['spa.UserProfile']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'notification_text': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
|
||||
'notification_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}),
|
||||
'target': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}),
|
||||
'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'to_notications'", 'to': "orm['spa.UserProfile']"}),
|
||||
'verb': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'})
|
||||
},
|
||||
'spa.purchaselink': {
|
||||
'Meta': {'object_name': 'PurchaseLink'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'track': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'purchase_link'", 'to': "orm['spa.Tracklist']"}),
|
||||
'url': ('django.db.models.fields.URLField', [], {'max_length': '200'})
|
||||
},
|
||||
'spa.recurrence': {
|
||||
'Meta': {'object_name': 'Recurrence', '_ormbases': ['spa._Lookup']},
|
||||
u'_lookup_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Lookup']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'spa.release': {
|
||||
'Meta': {'object_name': 'Release'},
|
||||
'embed_code': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 11, 27, 0, 0)'}),
|
||||
'release_description': ('django.db.models.fields.TextField', [], {}),
|
||||
'release_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
|
||||
'release_label': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Label']"}),
|
||||
'release_title': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"})
|
||||
},
|
||||
'spa.releaseaudio': {
|
||||
'Meta': {'object_name': 'ReleaseAudio'},
|
||||
'description': ('django.db.models.fields.TextField', [], {}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
|
||||
'release': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'release_audio'", 'null': 'True', 'to': "orm['spa.Release']"})
|
||||
},
|
||||
'spa.tracklist': {
|
||||
'Meta': {'object_name': 'Tracklist'},
|
||||
'artist': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'index': ('django.db.models.fields.SmallIntegerField', [], {}),
|
||||
'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tracklist'", 'to': "orm['spa.Mix']"}),
|
||||
'remixer': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'timeindex': ('django.db.models.fields.TimeField', [], {'null': 'True'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
|
||||
},
|
||||
'spa.userprofile': {
|
||||
'Meta': {'object_name': 'UserProfile'},
|
||||
'activity_sharing': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '1024', 'blank': 'True'}),
|
||||
'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}),
|
||||
'city': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
|
||||
'country': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}),
|
||||
'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}),
|
||||
'following': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'followers'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'last_known_session': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': 'True'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'default': 'None', 'max_length': '50', 'null': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': u"orm['auth.User']"})
|
||||
},
|
||||
'spa.venue': {
|
||||
'Meta': {'object_name': 'Venue'},
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
|
||||
'venue_address': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
|
||||
'venue_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}),
|
||||
'venue_name': ('django.db.models.fields.CharField', [], {'max_length': '250'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['spa']
|
||||
@@ -37,7 +37,7 @@ class Activity(_BaseModel):
|
||||
notification.from_user = self.user
|
||||
notification.to_user = self.get_target_user()
|
||||
notification.notification_text = "%s %s %s" % (
|
||||
self.user.get_nice_name() or "Anonymous", self.get_verb_past(), self.get_object_name_for_notification())
|
||||
self.user.get_nice_name() or "Anonymouse", self.get_verb_past(), self.get_object_name_for_notification())
|
||||
|
||||
notification.notification_url = self.get_object_url()
|
||||
notification.verb = self.get_verb_past()
|
||||
|
||||
@@ -8,7 +8,7 @@ class Comment(_BaseModel):
|
||||
class Meta:
|
||||
app_label = 'spa'
|
||||
|
||||
user = models.ForeignKey(User, editable=False)
|
||||
user = models.ForeignKey(User, editable=False, null=True, blank=True)
|
||||
mix = models.ForeignKey(Mix, editable=False, null=True, blank=True, related_name='comments')
|
||||
comment = models.CharField(max_length=1024)
|
||||
date_created = models.DateTimeField(auto_now=True)
|
||||
|
||||
@@ -2,10 +2,13 @@ import os
|
||||
import rfc822
|
||||
from datetime import datetime
|
||||
import urlparse
|
||||
from logilab.common.registry import ObjectNotFound
|
||||
from psycopg2.errorcodes import OBJECT_NOT_IN_PREREQUISITE_STATE
|
||||
from sorl.thumbnail import get_thumbnail
|
||||
from django.contrib.sites.models import Site
|
||||
from django.db import models
|
||||
from core.utils import url
|
||||
from core.utils.audio import Mp3FileNotFoundException
|
||||
from core.utils.audio.mp3 import mp3_length, tag_mp3
|
||||
from core.utils.url import unique_slugify
|
||||
from spa.models.activity import ActivityDownload, ActivityPlay
|
||||
@@ -28,11 +31,23 @@ def mix_image_name(instance, filename):
|
||||
class MixManager(models.Manager):
|
||||
pass
|
||||
|
||||
def get_by_id_or_slug(self, id_or_slug):
|
||||
"""
|
||||
Tries to get a mix using the slug first
|
||||
If this fails then try getting by id
|
||||
"""
|
||||
try:
|
||||
return super(MixManager, self).get(slug=id_or_slug)
|
||||
except ObjectNotFound:
|
||||
return super(MixManager, self).get(slug=id_or_slug)
|
||||
|
||||
|
||||
class Mix(_BaseModel):
|
||||
class Meta:
|
||||
app_label = 'spa'
|
||||
|
||||
objects = MixManager()
|
||||
|
||||
title = models.CharField(max_length=150)
|
||||
description = models.TextField()
|
||||
upload_date = models.DateTimeField(default=datetime.now())
|
||||
@@ -64,7 +79,11 @@ class Mix(_BaseModel):
|
||||
#Check for the unlikely event that the waveform has been generated
|
||||
if os.path.isfile(self.get_waveform_path()):
|
||||
self.waveform_generated = True
|
||||
self.duration = mp3_length(self.get_absolute_path())
|
||||
try:
|
||||
self.duration = mp3_length(self.get_absolute_path())
|
||||
except Mp3FileNotFoundException:
|
||||
#Not really bothered about this in save as it can be called before we have an mp3
|
||||
pass
|
||||
|
||||
super(Mix, self).save(force_insert, force_update, using, update_fields)
|
||||
|
||||
@@ -112,7 +131,6 @@ class Mix(_BaseModel):
|
||||
def get_waveform_url(self):
|
||||
|
||||
if self.waveform_generated and os.path.exists(self.get_waveform_path()):
|
||||
|
||||
waveform_root = localsettings.WAVEFORM_URL if hasattr(localsettings,
|
||||
'WAVEFORM_URL') else "%swaveforms" % settings.MEDIA_URL
|
||||
ret = "%s/%s.%s" % (waveform_root, self.uid, "png")
|
||||
@@ -130,7 +148,7 @@ class Mix(_BaseModel):
|
||||
name, extension = os.path.splitext(self.mix_image.file.name)
|
||||
return os.path.join(settings.MEDIA_ROOT, 'mix-images', "%s.%s", (self.uid, extension))
|
||||
|
||||
def get_image_url(self, size='160x160'):
|
||||
def get_image_url(self, size='160x160', default=''):
|
||||
try:
|
||||
ret = get_thumbnail(self.mix_image, size, crop='center')
|
||||
return "%s/%s" % (settings.MEDIA_URL, ret.name)
|
||||
|
||||
@@ -226,5 +226,5 @@ class UserProfile(_BaseModel):
|
||||
|
||||
@classmethod
|
||||
def get_default_moniker(cls):
|
||||
return "Anonymous"
|
||||
return "Anonymouse"
|
||||
|
||||
|
||||
@@ -13,14 +13,14 @@ register = template.Library()
|
||||
@register.filter
|
||||
def nice_name(user):
|
||||
if user == "":
|
||||
return "Anonymous"
|
||||
return "Anonymouse"
|
||||
if user.is_authenticated():
|
||||
profile = user.get_profile()
|
||||
if profile is not None:
|
||||
if profile.display_name <> "":
|
||||
return profile.display_name
|
||||
else:
|
||||
return "Anonymous"
|
||||
return "Anonymouse"
|
||||
|
||||
return user.get_full_name() or user.username
|
||||
|
||||
|
||||
@@ -75,11 +75,6 @@ define ['backbone', 'marionette', 'vent', 'utils',
|
||||
no: ->
|
||||
console.log("Controller: mixDeleteNO!!")
|
||||
|
||||
@listenTo vent, "mix:comment", (model, comment) ->
|
||||
console.log "App(vent): mix:favourite"
|
||||
model.save 'favourited', !model.get('favourited'), patch: true
|
||||
true
|
||||
|
||||
@listenTo vent, "user:follow", (model)->
|
||||
console.log "App(vent): user:follow"
|
||||
user = new UserItem({id: com.podnoms.settings.currentUser })
|
||||
|
||||
@@ -86,13 +86,6 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
this.listenTo(vent, "mix:comment", function(model, comment) {
|
||||
console.log("App(vent): mix:favourite");
|
||||
model.save('favourited', !model.get('favourited'), {
|
||||
patch: true
|
||||
});
|
||||
return true;
|
||||
});
|
||||
this.listenTo(vent, "user:follow", function(model) {
|
||||
var target, user,
|
||||
_this = this;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.3.3
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
||||
__hasProp = {}.hasOwnProperty,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
define(['backbone', 'backbone.relational'], function (Backbone) {
|
||||
define(['backbone', 'backbone-associations'], function (Backbone) {
|
||||
|
||||
var TastypieModel = Backbone.RelationalModel.extend({
|
||||
var TastypieModel = Backbone.AssociatedModel.extend({
|
||||
base_url: function () {
|
||||
var temp_url = Backbone.Model.prototype.url.call(this);
|
||||
return (temp_url.charAt(temp_url.length - 1) == '/' ? temp_url : temp_url + '/');
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
define ['app', 'marionette', 'vent', 'utils'
|
||||
'views/mix/mixListLayout', 'views/mix/mixListView', 'views/mix/mixDetailView'
|
||||
'views/mix/mixEditView', 'views/user/userProfileView', 'views/user/userListView', 'views/user/userEditView',
|
||||
'models/mix/mixItem', 'models/mix/mixCollection', 'models/user/userItem'],
|
||||
'models/mix/mixCollection', 'models/mix/mixItem', 'models/user/userItem'],
|
||||
(App, Marionette, vent, utils,
|
||||
MixListLayout, MixListView, MixDetailView,
|
||||
MixEditView, UserProfileView, UserListView, UserEditView,
|
||||
MixItem, MixCollection, UserItem)->
|
||||
MixCollection, MixItem, UserItem)->
|
||||
class DssController extends Marionette.Controller
|
||||
|
||||
initialize: ->
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['app', 'marionette', 'vent', 'utils', 'views/mix/mixListLayout', 'views/mix/mixListView', 'views/mix/mixDetailView', 'views/mix/mixEditView', 'views/user/userProfileView', 'views/user/userListView', 'views/user/userEditView', 'models/mix/mixItem', 'models/mix/mixCollection', 'models/user/userItem'], function(App, Marionette, vent, utils, MixListLayout, MixListView, MixDetailView, MixEditView, UserProfileView, UserListView, UserEditView, MixItem, MixCollection, UserItem) {
|
||||
define(['app', 'marionette', 'vent', 'utils', 'views/mix/mixListLayout', 'views/mix/mixListView', 'views/mix/mixDetailView', 'views/mix/mixEditView', 'views/user/userProfileView', 'views/user/userListView', 'views/user/userEditView', 'models/mix/mixCollection', 'models/mix/mixItem', 'models/user/userItem'], function(App, Marionette, vent, utils, MixListLayout, MixListView, MixDetailView, MixEditView, UserProfileView, UserListView, UserEditView, MixCollection, MixItem, UserItem) {
|
||||
var DssController;
|
||||
DssController = (function(_super) {
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
||||
__hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['app.lib/dssView', 'utils', 'ace-editable', 'lib/bootstrap-typeahead'], function(DssView, utils) {
|
||||
var EditableView, _ref;
|
||||
|
||||
var EditableView;
|
||||
EditableView = (function(_super) {
|
||||
|
||||
__extends(EditableView, _super);
|
||||
|
||||
function EditableView() {
|
||||
this.setupImageEditable = __bind(this.setupImageEditable, this); _ref = EditableView.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
this.setupImageEditable = __bind(this.setupImageEditable, this);
|
||||
return EditableView.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
EditableView.prototype.events = {
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
EditableView.prototype.changeSelect = function(evt) {
|
||||
var changed, obj, objInst, value;
|
||||
|
||||
changed = evt.currentTarget;
|
||||
if (id) {
|
||||
value = $(evt.currentTarget).val();
|
||||
@@ -34,7 +33,6 @@
|
||||
|
||||
EditableView.prototype.changed = function(evt) {
|
||||
var changed, obj, objInst, value;
|
||||
|
||||
return;
|
||||
changed = evt.currentTarget;
|
||||
if (changed.id) {
|
||||
@@ -54,7 +52,6 @@
|
||||
|
||||
EditableView.prototype._bakeForm = function(el, lookups) {
|
||||
var labels, mapped, model;
|
||||
|
||||
model = this.model;
|
||||
labels = void 0;
|
||||
mapped = void 0;
|
||||
@@ -107,7 +104,6 @@
|
||||
|
||||
EditableView.prototype._saveChanges = function() {
|
||||
var args, error, _results;
|
||||
|
||||
args = arguments;
|
||||
if (!this.model.isValid()) {
|
||||
if (this.model.errors) {
|
||||
@@ -128,9 +124,7 @@
|
||||
};
|
||||
|
||||
EditableView.prototype.setupImageEditable = function(options) {
|
||||
var e,
|
||||
_this = this;
|
||||
|
||||
var _this = this;
|
||||
$.fn.editable.defaults.mode = 'inline';
|
||||
try {
|
||||
if (/msie\s*(8|7|6)/.test(navigator.userAgent.toLowerCase())) {
|
||||
@@ -170,15 +164,13 @@
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (_error) {
|
||||
e = _error;
|
||||
} catch (e) {
|
||||
return console.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
EditableView.prototype.uploadImage = function(options) {
|
||||
var $form, deferred, e, fd, file_input, files, iframe_id;
|
||||
|
||||
var $form, deferred, fd, file_input, files, iframe_id;
|
||||
$form = options.el.next().find(".editableform:eq(0)");
|
||||
file_input = $form.find("input[type=file]:eq(0)");
|
||||
if (!("FormData" in window)) {
|
||||
@@ -196,7 +188,6 @@
|
||||
$form.get(0).submit();
|
||||
setTimeout((function() {
|
||||
var iframe;
|
||||
|
||||
iframe = document.getElementById(iframe_id);
|
||||
if (iframe != null) {
|
||||
iframe.src = "about:blank";
|
||||
@@ -211,8 +202,7 @@
|
||||
fd = null;
|
||||
try {
|
||||
fd = new FormData($form.get(0));
|
||||
} catch (_error) {
|
||||
e = _error;
|
||||
} catch (e) {
|
||||
fd = new FormData();
|
||||
$.each($form.serializeArray(), function(index, item) {
|
||||
return fd.append(item.name, item.value);
|
||||
@@ -238,7 +228,6 @@
|
||||
data: fd,
|
||||
xhr: function() {
|
||||
var req;
|
||||
|
||||
req = $.ajaxSettings.xhr();
|
||||
return req;
|
||||
},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
|
||||
define(['marionette'], function() {
|
||||
return new Backbone.Wreqr.EventAggregator;
|
||||
});
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['marionette'], function(Marionette) {
|
||||
var PanningRegion, getPrefixedCssProp, _ref;
|
||||
|
||||
var PanningRegion, getPrefixedCssProp;
|
||||
getPrefixedCssProp = function(baseProp) {
|
||||
var str;
|
||||
|
||||
str = Modernizr.prefixed(baseProp);
|
||||
str = str.replace(/([A-Z])/g, function(str, m1) {
|
||||
return "-" + m1.toLowerCase();
|
||||
@@ -16,18 +14,17 @@
|
||||
return str;
|
||||
};
|
||||
PanningRegion = (function(_super) {
|
||||
|
||||
__extends(PanningRegion, _super);
|
||||
|
||||
function PanningRegion() {
|
||||
_ref = PanningRegion.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
return PanningRegion.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
PanningRegion.prototype.el = "#content";
|
||||
|
||||
PanningRegion.prototype.initialize = function() {
|
||||
var transEndEventNames;
|
||||
|
||||
transEndEventNames = {
|
||||
WebkitTransition: "webkitTransitionEnd",
|
||||
MozTransition: "transitionend",
|
||||
@@ -43,7 +40,6 @@
|
||||
|
||||
PanningRegion.prototype.transitionToView = function(newView, type) {
|
||||
var self, view;
|
||||
|
||||
self = this;
|
||||
view = this.currentView;
|
||||
if (!view || view.isClosed) {
|
||||
@@ -53,7 +49,6 @@
|
||||
Marionette.triggerMethod.call(this, "willTransition", view);
|
||||
newView.on("render", function() {
|
||||
var $background, newViewMatrix, translation, worldBgMatrix, worldContentMatrix;
|
||||
|
||||
self.$el.off(self.transEndEventName);
|
||||
translation = void 0;
|
||||
if (type === "slide") {
|
||||
|
||||
@@ -41,18 +41,36 @@ define ['jquery', 'bootstrap', 'toastr'], ($, bootstrap, toastr) ->
|
||||
@modal "/dlg/PlayCountLoginAlert"
|
||||
true
|
||||
|
||||
toastOptions: ->
|
||||
toastr.options =
|
||||
closeButton: true
|
||||
debug: false
|
||||
positionClass: "toast-bottom-left"
|
||||
onclick: null
|
||||
showDuration: "300"
|
||||
hideDuration: "1000"
|
||||
timeOut: "5000"
|
||||
extendedTimeOut: "1000"
|
||||
showEasing: "swing"
|
||||
hideEasing: "linear"
|
||||
showMethod: "fadeIn"
|
||||
hideMethod: "fadeOut"
|
||||
|
||||
showError: (title, message) ->
|
||||
@toastOptions()
|
||||
toastr.error message, title
|
||||
|
||||
showWarning: (title, message) ->
|
||||
@toastOptions()
|
||||
toastr.warning message, title
|
||||
|
||||
showMessage: (title, message) ->
|
||||
toastOptions()
|
||||
toastr.success message, title
|
||||
|
||||
showAlert: (title, message) ->
|
||||
@showMessage title, message
|
||||
|
||||
showMessage: (title, message) ->
|
||||
toastr.success message, title
|
||||
|
||||
generateGuid: ->
|
||||
"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace /[xy]/g, (c) ->
|
||||
r = Math.random() * 16 | 0
|
||||
|
||||
@@ -58,18 +58,37 @@
|
||||
}
|
||||
return true;
|
||||
},
|
||||
toastOptions: function() {
|
||||
return toastr.options = {
|
||||
closeButton: true,
|
||||
debug: false,
|
||||
positionClass: "toast-bottom-left",
|
||||
onclick: null,
|
||||
showDuration: "300",
|
||||
hideDuration: "1000",
|
||||
timeOut: "5000",
|
||||
extendedTimeOut: "1000",
|
||||
showEasing: "swing",
|
||||
hideEasing: "linear",
|
||||
showMethod: "fadeIn",
|
||||
hideMethod: "fadeOut"
|
||||
};
|
||||
},
|
||||
showError: function(title, message) {
|
||||
this.toastOptions();
|
||||
return toastr.error(message, title);
|
||||
},
|
||||
showWarning: function(title, message) {
|
||||
this.toastOptions();
|
||||
return toastr.warning(message, title);
|
||||
},
|
||||
showMessage: function(title, message) {
|
||||
toastOptions();
|
||||
return toastr.success(message, title);
|
||||
},
|
||||
showAlert: function(title, message) {
|
||||
return this.showMessage(title, message);
|
||||
},
|
||||
showMessage: function(title, message) {
|
||||
return toastr.success(message, title);
|
||||
},
|
||||
generateGuid: function() {
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
||||
var r, v;
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['backbone', 'vent', 'models/activity/activityItem', 'app.lib/backbone.dss.model.collection'], function(Backbone, vent, ActivityItem, DssCollection) {
|
||||
var ActivityCollection, _ref;
|
||||
|
||||
var ActivityCollection;
|
||||
ActivityCollection = (function(_super) {
|
||||
|
||||
__extends(ActivityCollection, _super);
|
||||
|
||||
function ActivityCollection() {
|
||||
_ref = ActivityCollection.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
return ActivityCollection.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
ActivityCollection.prototype.model = ActivityItem;
|
||||
@@ -20,10 +19,8 @@
|
||||
|
||||
ActivityCollection.prototype.initialize = function() {
|
||||
var _this = this;
|
||||
|
||||
return this.listenTo(vent, "model:activity:new", function(url) {
|
||||
var item;
|
||||
|
||||
console.log("ActivityCollection: activity:new");
|
||||
item = new ActivityItem();
|
||||
return item.fetch({
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['backbone', 'moment'], function(Backbone, moment) {
|
||||
var ActivityItem, _ref;
|
||||
|
||||
var ActivityItem;
|
||||
ActivityItem = (function(_super) {
|
||||
|
||||
__extends(ActivityItem, _super);
|
||||
|
||||
function ActivityItem() {
|
||||
_ref = ActivityItem.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
return ActivityItem.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
ActivityItem.prototype.urlRoot = com.podnoms.settings.urlRoot + "activity/";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.3.3
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
define ['app.lib/backbone.dss.model'], \
|
||||
(DSSModel) ->
|
||||
class CommentItem extends DSSModel
|
||||
urlRoot: com.podnoms.settings.urlRoot + "comments/"
|
||||
defaults:
|
||||
avatar_image: com.podnoms.settings.avatarImage
|
||||
user_name: com.podnoms.settings.userName
|
||||
user_url: com.podnoms.settings.userUrl
|
||||
date_created: ""
|
||||
define ['backbone', 'backbone-associations'],
|
||||
(Backbone) ->
|
||||
class CommentItem extends Backbone.Model
|
||||
urlRoot: com.podnoms.settings.urlRoot + "comments"
|
||||
|
||||
CommentItem
|
||||
CommentItem
|
||||
@@ -1,31 +1,23 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['app.lib/backbone.dss.model'], function(DSSModel) {
|
||||
var CommentItem, _ref;
|
||||
|
||||
define(['backbone', 'backbone-associations'], function(Backbone) {
|
||||
var CommentItem;
|
||||
CommentItem = (function(_super) {
|
||||
|
||||
__extends(CommentItem, _super);
|
||||
|
||||
function CommentItem() {
|
||||
_ref = CommentItem.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
return CommentItem.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
CommentItem.prototype.urlRoot = com.podnoms.settings.urlRoot + "comments/";
|
||||
|
||||
CommentItem.prototype.defaults = {
|
||||
avatar_image: com.podnoms.settings.avatarImage,
|
||||
user_name: com.podnoms.settings.userName,
|
||||
user_url: com.podnoms.settings.userUrl,
|
||||
date_created: ""
|
||||
};
|
||||
CommentItem.prototype.urlRoot = com.podnoms.settings.urlRoot + "comments";
|
||||
|
||||
return CommentItem;
|
||||
|
||||
})(DSSModel);
|
||||
})(Backbone.Model);
|
||||
return CommentItem;
|
||||
});
|
||||
|
||||
|
||||
@@ -1,16 +1,29 @@
|
||||
define ['models/comment/commentCollection', 'models/comment/commentItem', 'app.lib/backbone.dss.model'], \
|
||||
(CommentCollection, CommentItem, DSSModel) ->
|
||||
class MixItem extends DSSModel
|
||||
urlRoot: com.podnoms.settings.urlRoot + "mix/"
|
||||
"""
|
||||
relations: [
|
||||
type: Backbone.HasMany
|
||||
key: "comments"
|
||||
relatedModel: CommentItem
|
||||
collectionType: CommentCollection
|
||||
reverseRelation:
|
||||
key: "hasItems"
|
||||
includeInJSON: "id"
|
||||
]
|
||||
"""
|
||||
define ['utils', 'vent', 'models/comment/commentCollection', 'models/comment/commentItem', 'app.lib/backbone.dss.model'],
|
||||
(utils, vent, CommentCollection, CommentItem, DssModel) ->
|
||||
class MixItem extends DssModel
|
||||
urlRoot: com.podnoms.settings.urlRoot + "mix/"
|
||||
|
||||
relations: [
|
||||
type: Backbone.Many #nature of the relation
|
||||
key: "comments" #attribute of Model
|
||||
relatedModel: CommentItem #AssociatedModel for attribute key
|
||||
]
|
||||
|
||||
addComment: (comment, success, error) ->
|
||||
c = undefined
|
||||
if comment
|
||||
c = @get("comments").create(
|
||||
comment: comment
|
||||
mix_id: @get("slug")
|
||||
)
|
||||
c.save null,
|
||||
success: ->
|
||||
success()
|
||||
|
||||
error: ->
|
||||
error()
|
||||
|
||||
else
|
||||
error "Comment cannot be empty"
|
||||
|
||||
MixItem
|
||||
@@ -1,27 +1,55 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['models/comment/commentCollection', 'models/comment/commentItem', 'app.lib/backbone.dss.model'], function(CommentCollection, CommentItem, DSSModel) {
|
||||
var MixItem, _ref;
|
||||
define(['utils', 'vent', 'models/comment/commentCollection', 'models/comment/commentItem', 'app.lib/backbone.dss.model'], function(utils, vent, CommentCollection, CommentItem, DssModel) {
|
||||
var MixItem;
|
||||
return MixItem = (function(_super) {
|
||||
|
||||
MixItem = (function(_super) {
|
||||
__extends(MixItem, _super);
|
||||
|
||||
function MixItem() {
|
||||
_ref = MixItem.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
return MixItem.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
MixItem.prototype.urlRoot = com.podnoms.settings.urlRoot + "mix/";
|
||||
|
||||
"relations: [\n type: Backbone.HasMany\n key: \"comments\"\n relatedModel: CommentItem\n collectionType: CommentCollection\n reverseRelation:\n key: \"hasItems\"\n includeInJSON: \"id\"\n ]";
|
||||
MixItem.prototype.relations = [
|
||||
{
|
||||
type: Backbone.Many,
|
||||
key: "comments",
|
||||
relatedModel: CommentItem
|
||||
}
|
||||
];
|
||||
|
||||
MixItem.prototype.addComment = function(comment, success, error) {
|
||||
var c;
|
||||
c = void 0;
|
||||
if (comment) {
|
||||
c = this.get("comments").create({
|
||||
comment: comment,
|
||||
mix_id: this.get("slug")
|
||||
});
|
||||
return c.save(null, {
|
||||
success: function() {
|
||||
return success();
|
||||
},
|
||||
error: function() {
|
||||
return error();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return error("Comment cannot be empty");
|
||||
}
|
||||
};
|
||||
|
||||
MixItem;
|
||||
|
||||
|
||||
return MixItem;
|
||||
|
||||
})(DSSModel);
|
||||
return MixItem;
|
||||
})(DssModel);
|
||||
});
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.3.3
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['backbone', 'models/user/userItem', 'app.lib/backbone.dss.model.collection'], function(Backbone, UserItem, DssCollection) {
|
||||
var UserCollection, _ref;
|
||||
|
||||
var UserCollection;
|
||||
UserCollection = (function(_super) {
|
||||
|
||||
__extends(UserCollection, _super);
|
||||
|
||||
function UserCollection() {
|
||||
_ref = UserCollection.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
return UserCollection.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
UserCollection.prototype.page = 0;
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['app.lib/backbone.dss.model'], function(DssModel) {
|
||||
var UserItem, _ref;
|
||||
|
||||
var UserItem;
|
||||
UserItem = (function(_super) {
|
||||
|
||||
__extends(UserItem, _super);
|
||||
|
||||
function UserItem() {
|
||||
_ref = UserItem.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
return UserItem.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
UserItem.prototype.urlRoot = com.podnoms.settings.urlRoot + "user/";
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['marionette', 'text!/tpl/ActivityListItemView'], function(Marionette, Template) {
|
||||
var ActivityItemView, _ref;
|
||||
|
||||
var ActivityItemView;
|
||||
return ActivityItemView = (function(_super) {
|
||||
|
||||
__extends(ActivityItemView, _super);
|
||||
|
||||
function ActivityItemView() {
|
||||
_ref = ActivityItemView.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
return ActivityItemView.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
ActivityItemView.prototype.template = _.template(Template);
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['marionette', 'models/activity/activityCollection', 'views/activity/activityItemView', 'text!/tpl/ActivityListView'], function(Marionette, ActivityCollection, ActivityItemView, Template) {
|
||||
var ActivityListView, _ref;
|
||||
|
||||
var ActivityListView;
|
||||
ActivityListView = (function(_super) {
|
||||
|
||||
__extends(ActivityListView, _super);
|
||||
|
||||
function ActivityListView() {
|
||||
_ref = ActivityListView.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
return ActivityListView.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
ActivityListView.prototype.template = _.template(Template);
|
||||
@@ -31,7 +30,6 @@
|
||||
|
||||
ActivityListView.prototype.appendHtml = function(collectionView, itemView, index) {
|
||||
var children, childrenContainer;
|
||||
|
||||
childrenContainer = (collectionView.itemViewContainer ? collectionView.$(collectionView.itemViewContainer) : collectionView.$el);
|
||||
children = childrenContainer.children();
|
||||
if (children.size() <= index) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.3.3
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['marionette', 'text!/tpl/CommentItemView'], function(Marionette, Template) {
|
||||
var CommentItemView, _ref;
|
||||
|
||||
var CommentItemView;
|
||||
CommentItemView = (function(_super) {
|
||||
|
||||
__extends(CommentItemView, _super);
|
||||
|
||||
function CommentItemView() {
|
||||
_ref = CommentItemView.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
return CommentItemView.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
CommentItemView.prototype.template = _.template(Template);
|
||||
|
||||
@@ -1,34 +1,58 @@
|
||||
define ['marionette',
|
||||
'utils',
|
||||
'models/mix/mixItem',
|
||||
'models/comment/commentItem',
|
||||
'models/comment/commentCollection',
|
||||
'views/comment/commentListView',
|
||||
'views/mix/mixItemView',
|
||||
'text!/tpl/MixDetailView',
|
||||
'vent'],
|
||||
(Marionette,
|
||||
MixItem,
|
||||
CommentItem,
|
||||
MixItemView,
|
||||
Template,
|
||||
vent) ->
|
||||
class MixDetailView extends Marionette.Layout
|
||||
(Marionette, utils, MixItem, CommentItem, CommentsCollection, CommentsListView, MixItemView, Template, vent) ->
|
||||
class MixDetailView extends Marionette.Layout
|
||||
|
||||
template: _.template(Template)
|
||||
regions:{
|
||||
mix: "#mix"
|
||||
comments: "#comments"
|
||||
}
|
||||
ui:
|
||||
commentText: '#comment-text'
|
||||
events:
|
||||
"click #btn-add-comment": "addComment"
|
||||
template: _.template(Template)
|
||||
regions:
|
||||
mix: "#mix"
|
||||
comments: "#comments"
|
||||
ui:
|
||||
commentText: '#comment-text'
|
||||
events:
|
||||
"click #btn-add-comment": "addComment"
|
||||
|
||||
initialize: ->
|
||||
@model.on('nested-change', @modelChanged)
|
||||
|
||||
addComment: ->
|
||||
comment = "123"
|
||||
onRender: ->
|
||||
view = new MixItemView({tagName: "div", className: "mix-listing audio-listing-single", model: @model})
|
||||
@mix.show view
|
||||
@renderComments()
|
||||
|
||||
onRender: ->
|
||||
view = new MixItemView({tagName: "div", className: "mix-listing audio-listing-single", model: @model})
|
||||
@mix.show(view)
|
||||
true
|
||||
renderComments: ->
|
||||
console.log "MixDetailView: Rendering comments"
|
||||
comments = new CommentsCollection()
|
||||
comments.url = @model.get("resource_uri") + "/comments/"
|
||||
comments.mix_id = @model.id
|
||||
comments.mix = @model
|
||||
comments.fetch success: (data) ->
|
||||
content = new CommentsListView(collection: comments).render()
|
||||
$("#comments", @el).html content.el
|
||||
true
|
||||
true
|
||||
|
||||
MixDetailView
|
||||
modelChanged: =>
|
||||
console.log("MixDetailView: modelChanged")
|
||||
@render()
|
||||
|
||||
addComment: ->
|
||||
activeTab = $("ul#mix-tab li.active", @el)
|
||||
comment = @ui.commentText.val()
|
||||
@model.addComment comment, (=>
|
||||
@ui.commentText.val ""
|
||||
utils.showMessage "Comment saved.."
|
||||
activeTab.tab().show()
|
||||
), (error) =>
|
||||
utils.showError "Woops \n" + error
|
||||
$('#comment-input').addClass('has-error')
|
||||
$('#comment-text').focus()
|
||||
|
||||
MixDetailView
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
|
||||
__hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['marionette', 'models/mix/mixItem', 'models/comment/commentItem', 'views/mix/mixItemView', 'text!/tpl/MixDetailView', 'vent'], function(Marionette, MixItem, CommentItem, MixItemView, Template, vent) {
|
||||
define(['marionette', 'utils', 'models/mix/mixItem', 'models/comment/commentItem', 'models/comment/commentCollection', 'views/comment/commentListView', 'views/mix/mixItemView', 'text!/tpl/MixDetailView', 'vent'], function(Marionette, utils, MixItem, CommentItem, CommentsCollection, CommentsListView, MixItemView, Template, vent) {
|
||||
var MixDetailView;
|
||||
MixDetailView = (function(_super) {
|
||||
return MixDetailView = (function(_super) {
|
||||
|
||||
__extends(MixDetailView, _super);
|
||||
|
||||
function MixDetailView() {
|
||||
this.modelChanged = __bind(this.modelChanged, this);
|
||||
return MixDetailView.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
@@ -28,9 +30,8 @@
|
||||
"click #btn-add-comment": "addComment"
|
||||
};
|
||||
|
||||
MixDetailView.prototype.addComment = function() {
|
||||
var comment;
|
||||
return comment = "123";
|
||||
MixDetailView.prototype.initialize = function() {
|
||||
return this.model.on('nested-change', this.modelChanged);
|
||||
};
|
||||
|
||||
MixDetailView.prototype.onRender = function() {
|
||||
@@ -41,13 +42,54 @@
|
||||
model: this.model
|
||||
});
|
||||
this.mix.show(view);
|
||||
return this.renderComments();
|
||||
};
|
||||
|
||||
MixDetailView.prototype.renderComments = function() {
|
||||
var comments;
|
||||
console.log("MixDetailView: Rendering comments");
|
||||
comments = new CommentsCollection();
|
||||
comments.url = this.model.get("resource_uri") + "/comments/";
|
||||
comments.mix_id = this.model.id;
|
||||
comments.mix = this.model;
|
||||
comments.fetch({
|
||||
success: function(data) {
|
||||
var content;
|
||||
content = new CommentsListView({
|
||||
collection: comments
|
||||
}).render();
|
||||
$("#comments", this.el).html(content.el);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
MixDetailView.prototype.modelChanged = function() {
|
||||
console.log("MixDetailView: modelChanged");
|
||||
return this.render();
|
||||
};
|
||||
|
||||
MixDetailView.prototype.addComment = function() {
|
||||
var activeTab, comment,
|
||||
_this = this;
|
||||
activeTab = $("ul#mix-tab li.active", this.el);
|
||||
comment = this.ui.commentText.val();
|
||||
this.model.addComment(comment, (function() {
|
||||
_this.ui.commentText.val("");
|
||||
utils.showMessage("Comment saved..");
|
||||
return activeTab.tab().show();
|
||||
}), function(error) {
|
||||
utils.showError("Woops \n" + error);
|
||||
$('#comment-input').addClass('has-error');
|
||||
return $('#comment-text').focus();
|
||||
});
|
||||
return MixDetailView;
|
||||
};
|
||||
|
||||
return MixDetailView;
|
||||
|
||||
})(Marionette.Layout);
|
||||
return MixDetailView;
|
||||
});
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
define ['moment', 'app', 'vent', 'marionette', 'utils',
|
||||
'models/comment/commentCollection',
|
||||
'views/comment/commentListView',
|
||||
'text!/tpl/MixListItemView'],
|
||||
(moment, App, vent, Marionette, utils,
|
||||
CommentsCollection,
|
||||
CommentsListView,
|
||||
Template) ->
|
||||
class MixItemView extends Marionette.ItemView
|
||||
template: _.template(Template)
|
||||
@@ -31,6 +27,7 @@ define ['moment', 'app', 'vent', 'marionette', 'utils',
|
||||
initialize: =>
|
||||
@listenTo(@model, 'change:favourited', @render)
|
||||
@listenTo(@model, 'change:liked', @render)
|
||||
@listenTo(@model, 'nested-change', @render)
|
||||
@listenTo(vent, 'mix:play', @mixPlay)
|
||||
@listenTo(vent, 'mix:pause', @mixPause)
|
||||
true
|
||||
@@ -40,10 +37,7 @@ define ['moment', 'app', 'vent', 'marionette', 'utils',
|
||||
if @model.get('duration')
|
||||
$('#player-duration-' + id, this.el).text(@model.secondsToHms('duration'))
|
||||
|
||||
|
||||
@renderGenres()
|
||||
@renderComments()
|
||||
|
||||
return
|
||||
|
||||
onShow: ->
|
||||
@@ -60,17 +54,6 @@ define ['moment', 'app', 'vent', 'marionette', 'utils',
|
||||
true
|
||||
true
|
||||
|
||||
renderComments: =>
|
||||
comments = new CommentsCollection()
|
||||
comments.url = @model.get("resource_uri") + "comments/"
|
||||
comments.mix_id = @model.id
|
||||
comments.mix = @model
|
||||
comments.fetch success: (data) ->
|
||||
content = new CommentsListView(collection: comments).render()
|
||||
$("#comments", @el).html content.el
|
||||
true
|
||||
true
|
||||
|
||||
doStart: =>
|
||||
console.log("MixItemView: mixStart")
|
||||
this.ui.playButton
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
__hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['moment', 'app', 'vent', 'marionette', 'utils', 'models/comment/commentCollection', 'views/comment/commentListView', 'text!/tpl/MixListItemView'], function(moment, App, vent, Marionette, utils, CommentsCollection, CommentsListView, Template) {
|
||||
define(['moment', 'app', 'vent', 'marionette', 'utils', 'text!/tpl/MixListItemView'], function(moment, App, vent, Marionette, utils, Template) {
|
||||
var MixItemView;
|
||||
MixItemView = (function(_super) {
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
function MixItemView() {
|
||||
this.doStart = __bind(this.doStart, this);
|
||||
|
||||
this.renderComments = __bind(this.renderComments, this);
|
||||
|
||||
this.renderGenres = __bind(this.renderGenres, this);
|
||||
|
||||
this.onRender = __bind(this.onRender, this);
|
||||
@@ -49,6 +47,7 @@
|
||||
MixItemView.prototype.initialize = function() {
|
||||
this.listenTo(this.model, 'change:favourited', this.render);
|
||||
this.listenTo(this.model, 'change:liked', this.render);
|
||||
this.listenTo(this.model, 'nested-change', this.render);
|
||||
this.listenTo(vent, 'mix:play', this.mixPlay);
|
||||
this.listenTo(vent, 'mix:pause', this.mixPause);
|
||||
return true;
|
||||
@@ -61,7 +60,6 @@
|
||||
$('#player-duration-' + id, this.el).text(this.model.secondsToHms('duration'));
|
||||
}
|
||||
this.renderGenres();
|
||||
this.renderComments();
|
||||
};
|
||||
|
||||
MixItemView.prototype.onShow = function() {
|
||||
@@ -82,25 +80,6 @@
|
||||
return true;
|
||||
};
|
||||
|
||||
MixItemView.prototype.renderComments = function() {
|
||||
var comments;
|
||||
comments = new CommentsCollection();
|
||||
comments.url = this.model.get("resource_uri") + "comments/";
|
||||
comments.mix_id = this.model.id;
|
||||
comments.mix = this.model;
|
||||
comments.fetch({
|
||||
success: function(data) {
|
||||
var content;
|
||||
content = new CommentsListView({
|
||||
collection: comments
|
||||
}).render();
|
||||
$("#comments", this.el).html(content.el);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
MixItemView.prototype.doStart = function() {
|
||||
console.log("MixItemView: mixStart");
|
||||
this.ui.playButton.toggleClass('play-button-small-start', false).toggleClass('play-button-small-resume', false).toggleClass('play-button-small-pause', true);
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['marionette', 'text!/tpl/NotificationsItemView'], function(Marionette, Template) {
|
||||
var NotificationsItemView, _ref;
|
||||
|
||||
var NotificationsItemView;
|
||||
return NotificationsItemView = (function(_super) {
|
||||
|
||||
__extends(NotificationsItemView, _super);
|
||||
|
||||
function NotificationsItemView() {
|
||||
_ref = NotificationsItemView.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
return NotificationsItemView.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
NotificationsItemView.prototype.template = _.template(Template);
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['underscore', 'backbone', 'marionette', 'vent', 'views/activity/activityListView', 'views/widgets/nowPlayingView', 'text!/tpl/SidebarView'], function(_, Backbone, Marionette, vent, ActivityListView, NowPlayingView, Template) {
|
||||
var SidebarView, _ref;
|
||||
|
||||
var SidebarView;
|
||||
SidebarView = (function(_super) {
|
||||
|
||||
__extends(SidebarView, _super);
|
||||
|
||||
function SidebarView() {
|
||||
_ref = SidebarView.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
return SidebarView.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
SidebarView.prototype.template = _.template(Template);
|
||||
@@ -44,7 +43,6 @@
|
||||
|
||||
SidebarView.prototype.liveStarted = function() {
|
||||
var _this = this;
|
||||
|
||||
console.log("SidebarView: livePlay");
|
||||
$.getJSON("ajax/live_now_playing/", function(data) {
|
||||
$(_this.topRegion.el).show();
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['app', 'utils', 'moment', 'marionette', 'vent', 'app.lib/editableView', 'models/user/userItem', 'text!/tpl/UserProfileView', 'ace-editable', 'wysiwyg'], function(App, utils, moment, Marionette, vent, EditableView, UserItem, Template) {
|
||||
var UserProfileView, _ref;
|
||||
|
||||
var UserProfileView;
|
||||
UserProfileView = (function(_super) {
|
||||
|
||||
__extends(UserProfileView, _super);
|
||||
|
||||
function UserProfileView() {
|
||||
_ref = UserProfileView.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
return UserProfileView.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
UserProfileView.prototype.template = _.template(Template);
|
||||
@@ -24,7 +23,6 @@
|
||||
|
||||
UserProfileView.prototype.onDomRefresh = function() {
|
||||
var _this = this;
|
||||
|
||||
console.log("UserProfileView: initialize");
|
||||
this.setupImageEditable({
|
||||
el: $("#avatar", this.el),
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['marionette', 'vent', 'text!/tpl/NowPlayingView'], function(Marionette, vent, Template) {
|
||||
var NowPlayingView, _ref;
|
||||
|
||||
var NowPlayingView;
|
||||
NowPlayingView = (function(_super) {
|
||||
|
||||
__extends(NowPlayingView, _super);
|
||||
|
||||
function NowPlayingView() {
|
||||
_ref = NowPlayingView.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
return NowPlayingView.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
NowPlayingView.prototype.template = _.template(Template);
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
// Generated by CoffeeScript 1.4.0
|
||||
(function() {
|
||||
var __hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
define(['jquery', 'underscore', 'marionette', 'vent', 'text!/tpl/SearchView', 'text!/tpl/SearchResultView', 'lib/bootstrap-typeahead'], function($, _, Marionette, vent, Template, SearchResultView) {
|
||||
var SearchView, _ref;
|
||||
|
||||
var SearchView;
|
||||
SearchView = (function(_super) {
|
||||
|
||||
__extends(SearchView, _super);
|
||||
|
||||
function SearchView() {
|
||||
_ref = SearchView.__super__.constructor.apply(this, arguments);
|
||||
return _ref;
|
||||
return SearchView.__super__.constructor.apply(this, arguments);
|
||||
}
|
||||
|
||||
SearchView.prototype.template = _.template(Template);
|
||||
@@ -23,7 +22,6 @@
|
||||
SearchView.prototype.engine = {
|
||||
compile: function(template) {
|
||||
var compiled;
|
||||
|
||||
compiled = _.template(template);
|
||||
return {
|
||||
render: function(context) {
|
||||
@@ -35,7 +33,6 @@
|
||||
|
||||
SearchView.prototype.onShow = function() {
|
||||
var t;
|
||||
|
||||
if (typeof typeahead !== "undefined" && typeahead !== null) {
|
||||
t = $('#search-text', this.el).typeahead({
|
||||
name: "search",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,169 +6,169 @@ ace.config = {
|
||||
}
|
||||
|
||||
ace.settings = {
|
||||
is : function(item, status) {
|
||||
//such as ace.settings.is('navbar', 'fixed')
|
||||
return (ace.data.get('settings', item+'-'+status) == 1)
|
||||
},
|
||||
exists : function(item, status) {
|
||||
return (ace.data.get('settings', item+'-'+status) !== null)
|
||||
},
|
||||
set : function(item, status) {
|
||||
ace.data.set('settings', item+'-'+status, 1)
|
||||
},
|
||||
unset : function(item, status) {
|
||||
ace.data.set('settings', item+'-'+status, -1)
|
||||
},
|
||||
remove : function(item, status) {
|
||||
ace.data.remove('settings', item+'-'+status)
|
||||
},
|
||||
is : function(item, status) {
|
||||
//such as ace.settings.is('navbar', 'fixed')
|
||||
return (ace.data.get('settings', item+'-'+status) == 1)
|
||||
},
|
||||
exists : function(item, status) {
|
||||
return (ace.data.get('settings', item+'-'+status) !== null)
|
||||
},
|
||||
set : function(item, status) {
|
||||
ace.data.set('settings', item+'-'+status, 1)
|
||||
},
|
||||
unset : function(item, status) {
|
||||
ace.data.set('settings', item+'-'+status, -1)
|
||||
},
|
||||
remove : function(item, status) {
|
||||
ace.data.remove('settings', item+'-'+status)
|
||||
},
|
||||
|
||||
navbar_fixed : function(fix) {
|
||||
fix = fix || false;
|
||||
if(!fix && ace.settings.is('sidebar', 'fixed')) {
|
||||
ace.settings.sidebar_fixed(false);
|
||||
}
|
||||
|
||||
var navbar = document.getElementById('navbar');
|
||||
if(fix) {
|
||||
if(!ace.hasClass(navbar , 'navbar-fixed-top')) ace.addClass(navbar , 'navbar-fixed-top');
|
||||
if(!ace.hasClass(document.body , 'navbar-fixed')) ace.addClass(document.body , 'navbar-fixed');
|
||||
|
||||
ace.settings.set('navbar', 'fixed');
|
||||
} else {
|
||||
ace.removeClass(navbar , 'navbar-fixed-top');
|
||||
ace.removeClass(document.body , 'navbar-fixed');
|
||||
|
||||
ace.settings.unset('navbar', 'fixed');
|
||||
}
|
||||
|
||||
document.getElementById('ace-settings-navbar').checked = fix;
|
||||
},
|
||||
navbar_fixed : function(fix) {
|
||||
fix = fix || false;
|
||||
if(!fix && ace.settings.is('sidebar', 'fixed')) {
|
||||
ace.settings.sidebar_fixed(false);
|
||||
}
|
||||
|
||||
var navbar = document.getElementById('navbar');
|
||||
if(fix) {
|
||||
if(!ace.hasClass(navbar , 'navbar-fixed-top')) ace.addClass(navbar , 'navbar-fixed-top');
|
||||
if(!ace.hasClass(document.body , 'navbar-fixed')) ace.addClass(document.body , 'navbar-fixed');
|
||||
|
||||
ace.settings.set('navbar', 'fixed');
|
||||
} else {
|
||||
ace.removeClass(navbar , 'navbar-fixed-top');
|
||||
ace.removeClass(document.body , 'navbar-fixed');
|
||||
|
||||
ace.settings.unset('navbar', 'fixed');
|
||||
}
|
||||
|
||||
document.getElementById('ace-settings-navbar').checked = fix;
|
||||
},
|
||||
|
||||
|
||||
breadcrumbs_fixed : function(fix) {
|
||||
fix = fix || false;
|
||||
if(fix && !ace.settings.is('sidebar', 'fixed')) {
|
||||
ace.settings.sidebar_fixed(true);
|
||||
}
|
||||
breadcrumbs_fixed : function(fix) {
|
||||
fix = fix || false;
|
||||
if(fix && !ace.settings.is('sidebar', 'fixed')) {
|
||||
ace.settings.sidebar_fixed(true);
|
||||
}
|
||||
|
||||
var breadcrumbs = document.getElementById('breadcrumbs');
|
||||
if(fix) {
|
||||
if(!ace.hasClass(breadcrumbs , 'breadcrumbs-fixed')) ace.addClass(breadcrumbs , 'breadcrumbs-fixed');
|
||||
if(!ace.hasClass(document.body , 'breadcrumbs-fixed')) ace.addClass(document.body , 'breadcrumbs-fixed');
|
||||
|
||||
ace.settings.set('breadcrumbs', 'fixed');
|
||||
} else {
|
||||
ace.removeClass(breadcrumbs , 'breadcrumbs-fixed');
|
||||
ace.removeClass(document.body , 'breadcrumbs-fixed');
|
||||
|
||||
ace.settings.unset('breadcrumbs', 'fixed');
|
||||
}
|
||||
document.getElementById('ace-settings-breadcrumbs').checked = fix;
|
||||
},
|
||||
var breadcrumbs = document.getElementById('breadcrumbs');
|
||||
if(fix) {
|
||||
if(!ace.hasClass(breadcrumbs , 'breadcrumbs-fixed')) ace.addClass(breadcrumbs , 'breadcrumbs-fixed');
|
||||
if(!ace.hasClass(document.body , 'breadcrumbs-fixed')) ace.addClass(document.body , 'breadcrumbs-fixed');
|
||||
|
||||
ace.settings.set('breadcrumbs', 'fixed');
|
||||
} else {
|
||||
ace.removeClass(breadcrumbs , 'breadcrumbs-fixed');
|
||||
ace.removeClass(document.body , 'breadcrumbs-fixed');
|
||||
|
||||
ace.settings.unset('breadcrumbs', 'fixed');
|
||||
}
|
||||
document.getElementById('ace-settings-breadcrumbs').checked = fix;
|
||||
},
|
||||
|
||||
|
||||
sidebar_fixed : function(fix) {
|
||||
fix = fix || false;
|
||||
if(!fix && ace.settings.is('breadcrumbs', 'fixed')) {
|
||||
ace.settings.breadcrumbs_fixed(false);
|
||||
}
|
||||
sidebar_fixed : function(fix) {
|
||||
fix = fix || false;
|
||||
if(!fix && ace.settings.is('breadcrumbs', 'fixed')) {
|
||||
ace.settings.breadcrumbs_fixed(false);
|
||||
}
|
||||
|
||||
if( fix && !ace.settings.is('navbar', 'fixed') ) {
|
||||
ace.settings.navbar_fixed(true);
|
||||
}
|
||||
if( fix && !ace.settings.is('navbar', 'fixed') ) {
|
||||
ace.settings.navbar_fixed(true);
|
||||
}
|
||||
|
||||
var sidebar = document.getElementById('sidebar');
|
||||
if(fix) {
|
||||
if( !ace.hasClass(sidebar , 'sidebar-fixed') ) ace.addClass(sidebar , 'sidebar-fixed');
|
||||
ace.settings.set('sidebar', 'fixed');
|
||||
} else {
|
||||
ace.removeClass(sidebar , 'sidebar-fixed');
|
||||
ace.settings.unset('sidebar', 'fixed');
|
||||
}
|
||||
document.getElementById('ace-settings-sidebar').checked = fix;
|
||||
},
|
||||
var sidebar = document.getElementById('sidebar');
|
||||
if(fix) {
|
||||
if( !ace.hasClass(sidebar , 'sidebar-fixed') ) ace.addClass(sidebar , 'sidebar-fixed');
|
||||
ace.settings.set('sidebar', 'fixed');
|
||||
} else {
|
||||
ace.removeClass(sidebar , 'sidebar-fixed');
|
||||
ace.settings.unset('sidebar', 'fixed');
|
||||
}
|
||||
document.getElementById('ace-settings-sidebar').checked = fix;
|
||||
},
|
||||
|
||||
main_container_fixed : function(inside) {
|
||||
inside = inside || false;
|
||||
main_container_fixed : function(inside) {
|
||||
inside = inside || false;
|
||||
|
||||
var main_container = document.getElementById('main-container');
|
||||
var navbar_container = document.getElementById('navbar-container');
|
||||
if(inside) {
|
||||
if( !ace.hasClass(main_container , 'container') ) ace.addClass(main_container , 'container');
|
||||
if( !ace.hasClass(navbar_container , 'container') ) ace.addClass(navbar_container , 'container');
|
||||
ace.settings.set('main-container', 'fixed');
|
||||
} else {
|
||||
ace.removeClass(main_container , 'container');
|
||||
ace.removeClass(navbar_container , 'container');
|
||||
ace.settings.unset('main-container', 'fixed');
|
||||
}
|
||||
document.getElementById('ace-settings-add-container').checked = inside;
|
||||
|
||||
|
||||
if(navigator.userAgent.match(/webkit/i)) {
|
||||
//webkit has a problem redrawing and moving around the sidebar background in realtime
|
||||
//so we do this, to force redraw
|
||||
//there will be no problems with webkit if the ".container" class is statically put inside HTML code.
|
||||
var sidebar = document.getElementById('sidebar')
|
||||
ace.toggleClass(sidebar , 'menu-min')
|
||||
setTimeout(function() { ace.toggleClass(sidebar , 'menu-min') } , 0)
|
||||
}
|
||||
},
|
||||
var main_container = document.getElementById('main-container');
|
||||
var navbar_container = document.getElementById('navbar-container');
|
||||
if(inside) {
|
||||
if( !ace.hasClass(main_container , 'container') ) ace.addClass(main_container , 'container');
|
||||
if( !ace.hasClass(navbar_container , 'container') ) ace.addClass(navbar_container , 'container');
|
||||
ace.settings.set('main-container', 'fixed');
|
||||
} else {
|
||||
ace.removeClass(main_container , 'container');
|
||||
ace.removeClass(navbar_container , 'container');
|
||||
ace.settings.unset('main-container', 'fixed');
|
||||
}
|
||||
document.getElementById('ace-settings-add-container').checked = inside;
|
||||
|
||||
|
||||
if(navigator.userAgent.match(/webkit/i)) {
|
||||
//webkit has a problem redrawing and moving around the sidebar background in realtime
|
||||
//so we do this, to force redraw
|
||||
//there will be no problems with webkit if the ".container" class is statically put inside HTML code.
|
||||
var sidebar = document.getElementById('sidebar')
|
||||
ace.toggleClass(sidebar , 'menu-min')
|
||||
setTimeout(function() { ace.toggleClass(sidebar , 'menu-min') } , 0)
|
||||
}
|
||||
},
|
||||
|
||||
sidebar_collapsed : function(collpase) {
|
||||
collpase = collpase || false;
|
||||
sidebar_collapsed : function(collpase) {
|
||||
collpase = collpase || false;
|
||||
|
||||
var sidebar = document.getElementById('sidebar');
|
||||
var icon = document.getElementById('sidebar-collapse').querySelector('[class*="icon-"]');
|
||||
var $icon1 = icon.getAttribute('data-icon1');//the icon for expanded state
|
||||
var $icon2 = icon.getAttribute('data-icon2');//the icon for collapsed state
|
||||
var sidebar = document.getElementById('sidebar');
|
||||
var icon = document.getElementById('sidebar-collapse').querySelector('[class*="icon-"]');
|
||||
var $icon1 = icon.getAttribute('data-icon1');//the icon for expanded state
|
||||
var $icon2 = icon.getAttribute('data-icon2');//the icon for collapsed state
|
||||
|
||||
if(collpase) {
|
||||
ace.addClass(sidebar , 'menu-min');
|
||||
ace.removeClass(icon , $icon1);
|
||||
ace.addClass(icon , $icon2);
|
||||
if(collpase) {
|
||||
ace.addClass(sidebar , 'menu-min');
|
||||
ace.removeClass(icon , $icon1);
|
||||
ace.addClass(icon , $icon2);
|
||||
|
||||
ace.settings.set('sidebar', 'collapsed');
|
||||
} else {
|
||||
ace.removeClass(sidebar , 'menu-min');
|
||||
ace.removeClass(icon , $icon2);
|
||||
ace.addClass(icon , $icon1);
|
||||
ace.settings.set('sidebar', 'collapsed');
|
||||
} else {
|
||||
ace.removeClass(sidebar , 'menu-min');
|
||||
ace.removeClass(icon , $icon2);
|
||||
ace.addClass(icon , $icon1);
|
||||
|
||||
ace.settings.unset('sidebar', 'collapsed');
|
||||
}
|
||||
ace.settings.unset('sidebar', 'collapsed');
|
||||
}
|
||||
|
||||
},
|
||||
/**
|
||||
select_skin : function(skin) {
|
||||
}
|
||||
*/
|
||||
},
|
||||
/**
|
||||
select_skin : function(skin) {
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
//check the status of something
|
||||
ace.settings.check = function(item, val) {
|
||||
if(! ace.settings.exists(item, val) ) return;//no such setting specified
|
||||
var status = ace.settings.is(item, val);//is breadcrumbs-fixed? or is sidebar-collapsed? etc
|
||||
|
||||
var mustHaveClass = {
|
||||
'navbar-fixed' : 'navbar-fixed-top',
|
||||
'sidebar-fixed' : 'sidebar-fixed',
|
||||
'breadcrumbs-fixed' : 'breadcrumbs-fixed',
|
||||
'sidebar-collapsed' : 'menu-min',
|
||||
'main-container-fixed' : 'container'
|
||||
}
|
||||
if(! ace.settings.exists(item, val) ) return;//no such setting specified
|
||||
var status = ace.settings.is(item, val);//is breadcrumbs-fixed? or is sidebar-collapsed? etc
|
||||
|
||||
var mustHaveClass = {
|
||||
'navbar-fixed' : 'navbar-fixed-top',
|
||||
'sidebar-fixed' : 'sidebar-fixed',
|
||||
'breadcrumbs-fixed' : 'breadcrumbs-fixed',
|
||||
'sidebar-collapsed' : 'menu-min',
|
||||
'main-container-fixed' : 'container'
|
||||
}
|
||||
|
||||
|
||||
//if an element doesn't have a specified class, but saved settings say it should, then add it
|
||||
//for example, sidebar isn't .fixed, but user fixed it on a previous page
|
||||
//or if an element has a specified class, but saved settings say it shouldn't, then remove it
|
||||
//for example, sidebar by default is minimized (.menu-min hard coded), but user expanded it and now shouldn't have 'menu-min' class
|
||||
|
||||
var target = document.getElementById(item);//#navbar, #sidebar, #breadcrumbs
|
||||
if(status != ace.hasClass(target , mustHaveClass[item+'-'+val])) {
|
||||
ace.settings[item.replace('-','_')+'_'+val](status);//call the relevant function to mage the changes
|
||||
}
|
||||
//if an element doesn't have a specified class, but saved settings say it should, then add it
|
||||
//for example, sidebar isn't .fixed, but user fixed it on a previous page
|
||||
//or if an element has a specified class, but saved settings say it shouldn't, then remove it
|
||||
//for example, sidebar by default is minimized (.menu-min hard coded), but user expanded it and now shouldn't have 'menu-min' class
|
||||
|
||||
var target = document.getElementById(item);//#navbar, #sidebar, #breadcrumbs
|
||||
if(status != ace.hasClass(target , mustHaveClass[item+'-'+val])) {
|
||||
ace.settings[item.replace('-','_')+'_'+val](status);//call the relevant function to mage the changes
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -181,93 +181,93 @@ ace.settings.check = function(item, val) {
|
||||
//method == 2, use cookies
|
||||
//method not specified, use localStorage if available, otherwise cookies
|
||||
ace.data_storage = function(method, undefined) {
|
||||
var prefix = 'ace.';
|
||||
var prefix = 'ace.';
|
||||
|
||||
var storage = null;
|
||||
var type = 0;
|
||||
|
||||
if((method == 1 || method === undefined) && 'localStorage' in window && window['localStorage'] !== null) {
|
||||
storage = ace.storage;
|
||||
type = 1;
|
||||
}
|
||||
else if(storage == null && (method == 2 || method === undefined) && 'cookie' in document && document['cookie'] !== null) {
|
||||
storage = ace.cookie;
|
||||
type = 2;
|
||||
}
|
||||
var storage = null;
|
||||
var type = 0;
|
||||
|
||||
if((method == 1 || method === undefined) && 'localStorage' in window && window['localStorage'] !== null) {
|
||||
storage = ace.storage;
|
||||
type = 1;
|
||||
}
|
||||
else if(storage == null && (method == 2 || method === undefined) && 'cookie' in document && document['cookie'] !== null) {
|
||||
storage = ace.cookie;
|
||||
type = 2;
|
||||
}
|
||||
|
||||
//var data = {}
|
||||
this.set = function(namespace, key, value, undefined) {
|
||||
if(!storage) return;
|
||||
|
||||
if(value === undefined) {//no namespace here?
|
||||
value = key;
|
||||
key = namespace;
|
||||
//var data = {}
|
||||
this.set = function(namespace, key, value, undefined) {
|
||||
if(!storage) return;
|
||||
|
||||
if(value === undefined) {//no namespace here?
|
||||
value = key;
|
||||
key = namespace;
|
||||
|
||||
if(value == null) storage.remove(prefix+key)
|
||||
else {
|
||||
if(type == 1)
|
||||
storage.set(prefix+key, value)
|
||||
else if(type == 2)
|
||||
storage.set(prefix+key, value, ace.config.cookie_expiry)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(type == 1) {//localStorage
|
||||
if(value == null) storage.remove(prefix+namespace+'.'+key)
|
||||
else storage.set(prefix+namespace+'.'+key, value);
|
||||
}
|
||||
else if(type == 2) {//cookie
|
||||
var val = storage.get(prefix+namespace);
|
||||
var tmp = val ? JSON.parse(val) : {};
|
||||
if(value == null) storage.remove(prefix+key)
|
||||
else {
|
||||
if(type == 1)
|
||||
storage.set(prefix+key, value)
|
||||
else if(type == 2)
|
||||
storage.set(prefix+key, value, ace.config.cookie_expiry)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(type == 1) {//localStorage
|
||||
if(value == null) storage.remove(prefix+namespace+'.'+key)
|
||||
else storage.set(prefix+namespace+'.'+key, value);
|
||||
}
|
||||
else if(type == 2) {//cookie
|
||||
var val = storage.get(prefix+namespace);
|
||||
var tmp = val ? JSON.parse(val) : {};
|
||||
|
||||
if(value == null) {
|
||||
delete tmp[key];//remove
|
||||
if(ace.sizeof(tmp) == 0) {//no other elements in this cookie, so delete it
|
||||
storage.remove(prefix+namespace);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
tmp[key] = value;
|
||||
}
|
||||
if(value == null) {
|
||||
delete tmp[key];//remove
|
||||
if(ace.sizeof(tmp) == 0) {//no other elements in this cookie, so delete it
|
||||
storage.remove(prefix+namespace);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
tmp[key] = value;
|
||||
}
|
||||
|
||||
storage.set(prefix+namespace , JSON.stringify(tmp), ace.config.cookie_expiry)
|
||||
}
|
||||
}
|
||||
}
|
||||
storage.set(prefix+namespace , JSON.stringify(tmp), ace.config.cookie_expiry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.get = function(namespace, key, undefined) {
|
||||
if(!storage) return null;
|
||||
|
||||
if(key === undefined) {//no namespace here?
|
||||
key = namespace;
|
||||
return storage.get(prefix+key);
|
||||
}
|
||||
else {
|
||||
if(type == 1) {//localStorage
|
||||
return storage.get(prefix+namespace+'.'+key);
|
||||
}
|
||||
else if(type == 2) {//cookie
|
||||
var val = storage.get(prefix+namespace);
|
||||
var tmp = val ? JSON.parse(val) : {};
|
||||
return key in tmp ? tmp[key] : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.get = function(namespace, key, undefined) {
|
||||
if(!storage) return null;
|
||||
|
||||
if(key === undefined) {//no namespace here?
|
||||
key = namespace;
|
||||
return storage.get(prefix+key);
|
||||
}
|
||||
else {
|
||||
if(type == 1) {//localStorage
|
||||
return storage.get(prefix+namespace+'.'+key);
|
||||
}
|
||||
else if(type == 2) {//cookie
|
||||
var val = storage.get(prefix+namespace);
|
||||
var tmp = val ? JSON.parse(val) : {};
|
||||
return key in tmp ? tmp[key] : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.remove = function(namespace, key, undefined) {
|
||||
if(!storage) return;
|
||||
|
||||
if(key === undefined) {
|
||||
key = namespace
|
||||
this.set(key, null);
|
||||
}
|
||||
else {
|
||||
this.set(namespace, key, null);
|
||||
}
|
||||
}
|
||||
|
||||
this.remove = function(namespace, key, undefined) {
|
||||
if(!storage) return;
|
||||
|
||||
if(key === undefined) {
|
||||
key = namespace
|
||||
this.set(key, null);
|
||||
}
|
||||
else {
|
||||
this.set(namespace, key, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -276,84 +276,84 @@ ace.data_storage = function(method, undefined) {
|
||||
|
||||
//cookie storage
|
||||
ace.cookie = {
|
||||
// The following functions are from Cookie.js class in TinyMCE, Moxiecode, used under LGPL.
|
||||
// The following functions are from Cookie.js class in TinyMCE, Moxiecode, used under LGPL.
|
||||
|
||||
/**
|
||||
* Get a cookie.
|
||||
*/
|
||||
get : function(name) {
|
||||
var cookie = document.cookie, e, p = name + "=", b;
|
||||
/**
|
||||
* Get a cookie.
|
||||
*/
|
||||
get : function(name) {
|
||||
var cookie = document.cookie, e, p = name + "=", b;
|
||||
|
||||
if ( !cookie )
|
||||
return;
|
||||
if ( !cookie )
|
||||
return;
|
||||
|
||||
b = cookie.indexOf("; " + p);
|
||||
b = cookie.indexOf("; " + p);
|
||||
|
||||
if ( b == -1 ) {
|
||||
b = cookie.indexOf(p);
|
||||
if ( b == -1 ) {
|
||||
b = cookie.indexOf(p);
|
||||
|
||||
if ( b != 0 )
|
||||
return null;
|
||||
if ( b != 0 )
|
||||
return null;
|
||||
|
||||
} else {
|
||||
b += 2;
|
||||
}
|
||||
} else {
|
||||
b += 2;
|
||||
}
|
||||
|
||||
e = cookie.indexOf(";", b);
|
||||
e = cookie.indexOf(";", b);
|
||||
|
||||
if ( e == -1 )
|
||||
e = cookie.length;
|
||||
if ( e == -1 )
|
||||
e = cookie.length;
|
||||
|
||||
return decodeURIComponent( cookie.substring(b + p.length, e) );
|
||||
},
|
||||
return decodeURIComponent( cookie.substring(b + p.length, e) );
|
||||
},
|
||||
|
||||
/**
|
||||
* Set a cookie.
|
||||
*
|
||||
* The 'expires' arg can be either a JS Date() object set to the expiration date (back-compat)
|
||||
* or the number of seconds until expiration
|
||||
*/
|
||||
set : function(name, value, expires, path, domain, secure) {
|
||||
var d = new Date();
|
||||
/**
|
||||
* Set a cookie.
|
||||
*
|
||||
* The 'expires' arg can be either a JS Date() object set to the expiration date (back-compat)
|
||||
* or the number of seconds until expiration
|
||||
*/
|
||||
set : function(name, value, expires, path, domain, secure) {
|
||||
var d = new Date();
|
||||
|
||||
if ( typeof(expires) == 'object' && expires.toGMTString ) {
|
||||
expires = expires.toGMTString();
|
||||
} else if ( parseInt(expires, 10) ) {
|
||||
d.setTime( d.getTime() + ( parseInt(expires, 10) * 1000 ) ); // time must be in miliseconds
|
||||
expires = d.toGMTString();
|
||||
} else {
|
||||
expires = '';
|
||||
}
|
||||
if ( typeof(expires) == 'object' && expires.toGMTString ) {
|
||||
expires = expires.toGMTString();
|
||||
} else if ( parseInt(expires, 10) ) {
|
||||
d.setTime( d.getTime() + ( parseInt(expires, 10) * 1000 ) ); // time must be in miliseconds
|
||||
expires = d.toGMTString();
|
||||
} else {
|
||||
expires = '';
|
||||
}
|
||||
|
||||
document.cookie = name + "=" + encodeURIComponent(value) +
|
||||
((expires) ? "; expires=" + expires : "") +
|
||||
((path) ? "; path=" + path : "") +
|
||||
((domain) ? "; domain=" + domain : "") +
|
||||
((secure) ? "; secure" : "");
|
||||
},
|
||||
document.cookie = name + "=" + encodeURIComponent(value) +
|
||||
((expires) ? "; expires=" + expires : "") +
|
||||
((path) ? "; path=" + path : "") +
|
||||
((domain) ? "; domain=" + domain : "") +
|
||||
((secure) ? "; secure" : "");
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove a cookie.
|
||||
*
|
||||
* This is done by setting it to an empty value and setting the expiration time in the past.
|
||||
*/
|
||||
remove : function(name, path) {
|
||||
this.set(name, '', -1000, path);
|
||||
}
|
||||
/**
|
||||
* Remove a cookie.
|
||||
*
|
||||
* This is done by setting it to an empty value and setting the expiration time in the past.
|
||||
*/
|
||||
remove : function(name, path) {
|
||||
this.set(name, '', -1000, path);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//local storage
|
||||
ace.storage = {
|
||||
get: function(key) {
|
||||
return window['localStorage'].getItem(key);
|
||||
},
|
||||
set: function(key, value) {
|
||||
window['localStorage'].setItem(key , value);
|
||||
},
|
||||
remove: function(key) {
|
||||
window['localStorage'].removeItem(key);
|
||||
}
|
||||
get: function(key) {
|
||||
return window['localStorage'].getItem(key);
|
||||
},
|
||||
set: function(key, value) {
|
||||
window['localStorage'].setItem(key , value);
|
||||
},
|
||||
remove: function(key) {
|
||||
window['localStorage'].removeItem(key);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -364,34 +364,34 @@ ace.storage = {
|
||||
//count the number of properties in an object
|
||||
//useful for getting the number of elements in an associative array
|
||||
ace.sizeof = function(obj) {
|
||||
var size = 0;
|
||||
for(var key in obj) if(obj.hasOwnProperty(key)) size++;
|
||||
return size;
|
||||
var size = 0;
|
||||
for(var key in obj) if(obj.hasOwnProperty(key)) size++;
|
||||
return size;
|
||||
}
|
||||
|
||||
//because jQuery may not be loaded at this stage, we use our own toggleClass
|
||||
ace.hasClass = function(elem, className) {
|
||||
return (" " + elem.className + " ").indexOf(" " + className + " ") > -1;
|
||||
return (" " + elem.className + " ").indexOf(" " + className + " ") > -1;
|
||||
}
|
||||
ace.addClass = function(elem, className) {
|
||||
if (!ace.hasClass(elem, className)) {
|
||||
var currentClass = elem.className;
|
||||
elem.className = currentClass + (currentClass.length? " " : "") + className;
|
||||
var currentClass = elem.className;
|
||||
elem.className = currentClass + (currentClass.length? " " : "") + className;
|
||||
}
|
||||
}
|
||||
ace.removeClass = function(elem, className) {ace.replaceClass(elem, className);}
|
||||
|
||||
ace.replaceClass = function(elem, className, newClass) {
|
||||
var classToRemove = new RegExp(("(^|\\s)" + className + "(\\s|$)"), "i");
|
||||
elem.className = elem.className.replace(classToRemove, function (match, p1, p2) {
|
||||
return newClass? (p1 + newClass + p2) : " ";
|
||||
}).replace(/^\s+|\s+$/g, "");
|
||||
var classToRemove = new RegExp(("(^|\\s)" + className + "(\\s|$)"), "i");
|
||||
elem.className = elem.className.replace(classToRemove, function (match, p1, p2) {
|
||||
return newClass? (p1 + newClass + p2) : " ";
|
||||
}).replace(/^\s+|\s+$/g, "");
|
||||
}
|
||||
|
||||
ace.toggleClass = function(elem, className) {
|
||||
if(ace.hasClass(elem, className))
|
||||
ace.removeClass(elem, className);
|
||||
else ace.addClass(elem, className);
|
||||
if(ace.hasClass(elem, className))
|
||||
ace.removeClass(elem, className);
|
||||
else ace.addClass(elem, className);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,85 +1,85 @@
|
||||
if(! ('ace' in window) ) window['ace'] = {}
|
||||
jQuery(function($) {
|
||||
//at some places we try to use 'tap' event instead of 'click' if jquery mobile plugin is available
|
||||
window['ace'].click_event = $.fn.tap ? "tap" : "click";
|
||||
//at some places we try to use 'tap' event instead of 'click' if jquery mobile plugin is available
|
||||
window['ace'].click_event = $.fn.tap ? "tap" : "click";
|
||||
});
|
||||
|
||||
ace.handle_side_menu = function($) {
|
||||
$('#menu-toggler').on(ace.click_event, function() {
|
||||
$('#sidebar').toggleClass('display');
|
||||
$(this).toggleClass('display');
|
||||
return false;
|
||||
});
|
||||
//mini
|
||||
var $minimized = $('#sidebar').hasClass('menu-min');
|
||||
$('#sidebar-collapse').on(ace.click_event, function(){
|
||||
$minimized = $('#sidebar').hasClass('menu-min');
|
||||
ace.settings.sidebar_collapsed(!$minimized);//@ ace-extra.js
|
||||
});
|
||||
$('#menu-toggler').on(ace.click_event, function() {
|
||||
$('#sidebar').toggleClass('display');
|
||||
$(this).toggleClass('display');
|
||||
return false;
|
||||
});
|
||||
//mini
|
||||
var $minimized = $('#sidebar').hasClass('menu-min');
|
||||
$('#sidebar-collapse').on(ace.click_event, function(){
|
||||
$minimized = $('#sidebar').hasClass('menu-min');
|
||||
ace.settings.sidebar_collapsed(!$minimized);//@ ace-extra.js
|
||||
});
|
||||
|
||||
var touch = "ontouchend" in document;
|
||||
//opening submenu
|
||||
$('.nav-list').on(ace.click_event, function(e){
|
||||
//check to see if we have clicked on an element which is inside a .dropdown-toggle element?!
|
||||
//if so, it means we should toggle a submenu
|
||||
var link_element = $(e.target).closest('a');
|
||||
if(!link_element || link_element.length == 0) return;//if not clicked inside a link element
|
||||
|
||||
$minimized = $('#sidebar').hasClass('menu-min');
|
||||
|
||||
if(! link_element.hasClass('dropdown-toggle') ) {//it doesn't have a submenu return
|
||||
//just one thing before we return
|
||||
//if sidebar is collapsed(minimized) and we click on a first level menu item
|
||||
//and the click is on the icon, not on the menu text then let's cancel event and cancel navigation
|
||||
//Good for touch devices, that when the icon is tapped to see the menu text, navigation is cancelled
|
||||
//navigation is only done when menu text is tapped
|
||||
if($minimized && ace.click_event == "tap" &&
|
||||
link_element.get(0).parentNode.parentNode == this /*.nav-list*/ )//i.e. only level-1 links
|
||||
{
|
||||
var text = link_element.find('.menu-text').get(0);
|
||||
if( e.target != text && !$.contains(text , e.target) )//not clicking on the text or its children
|
||||
return false;
|
||||
}
|
||||
var touch = "ontouchend" in document;
|
||||
//opening submenu
|
||||
$('.nav-list').on(ace.click_event, function(e){
|
||||
//check to see if we have clicked on an element which is inside a .dropdown-toggle element?!
|
||||
//if so, it means we should toggle a submenu
|
||||
var link_element = $(e.target).closest('a');
|
||||
if(!link_element || link_element.length == 0) return;//if not clicked inside a link element
|
||||
|
||||
$minimized = $('#sidebar').hasClass('menu-min');
|
||||
|
||||
if(! link_element.hasClass('dropdown-toggle') ) {//it doesn't have a submenu return
|
||||
//just one thing before we return
|
||||
//if sidebar is collapsed(minimized) and we click on a first level menu item
|
||||
//and the click is on the icon, not on the menu text then let's cancel event and cancel navigation
|
||||
//Good for touch devices, that when the icon is tapped to see the menu text, navigation is cancelled
|
||||
//navigation is only done when menu text is tapped
|
||||
if($minimized && ace.click_event == "tap" &&
|
||||
link_element.get(0).parentNode.parentNode == this /*.nav-list*/ )//i.e. only level-1 links
|
||||
{
|
||||
var text = link_element.find('.menu-text').get(0);
|
||||
if( e.target != text && !$.contains(text , e.target) )//not clicking on the text or its children
|
||||
return false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
//
|
||||
var sub = link_element.next().get(0);
|
||||
return;
|
||||
}
|
||||
//
|
||||
var sub = link_element.next().get(0);
|
||||
|
||||
//if we are opening this submenu, close all other submenus except the ".active" one
|
||||
if(! $(sub).is(':visible') ) {//if not open and visible, let's open it and make it visible
|
||||
var parent_ul = $(sub.parentNode).closest('ul');
|
||||
if($minimized && parent_ul.hasClass('nav-list')) return;
|
||||
|
||||
parent_ul.find('> .open > .submenu').each(function(){
|
||||
//close all other open submenus except for the active one
|
||||
if(this != sub && !$(this.parentNode).hasClass('active')) {
|
||||
$(this).slideUp(200).parent().removeClass('open');
|
||||
|
||||
//uncomment the following line to close all submenus on deeper levels when closing a submenu
|
||||
//$(this).find('.open > .submenu').slideUp(0).parent().removeClass('open');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
//uncomment the following line to close all submenus on deeper levels when closing a submenu
|
||||
//$(sub).find('.open > .submenu').slideUp(0).parent().removeClass('open');
|
||||
}
|
||||
//if we are opening this submenu, close all other submenus except the ".active" one
|
||||
if(! $(sub).is(':visible') ) {//if not open and visible, let's open it and make it visible
|
||||
var parent_ul = $(sub.parentNode).closest('ul');
|
||||
if($minimized && parent_ul.hasClass('nav-list')) return;
|
||||
|
||||
parent_ul.find('> .open > .submenu').each(function(){
|
||||
//close all other open submenus except for the active one
|
||||
if(this != sub && !$(this.parentNode).hasClass('active')) {
|
||||
$(this).slideUp(200).parent().removeClass('open');
|
||||
|
||||
//uncomment the following line to close all submenus on deeper levels when closing a submenu
|
||||
//$(this).find('.open > .submenu').slideUp(0).parent().removeClass('open');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
//uncomment the following line to close all submenus on deeper levels when closing a submenu
|
||||
//$(sub).find('.open > .submenu').slideUp(0).parent().removeClass('open');
|
||||
}
|
||||
|
||||
if($minimized && $(sub.parentNode.parentNode).hasClass('nav-list')) return false;
|
||||
if($minimized && $(sub.parentNode.parentNode).hasClass('nav-list')) return false;
|
||||
|
||||
$(sub).slideToggle(200).parent().toggleClass('open');
|
||||
return false;
|
||||
})
|
||||
$(sub).slideToggle(200).parent().toggleClass('open');
|
||||
return false;
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
ace.general_things = function($) {
|
||||
$('.ace-nav [class*="icon-animated-"]').closest('a').on('click', function(){
|
||||
var icon = $(this).find('[class*="icon-animated-"]').eq(0);
|
||||
var $match = icon.attr('class').match(/icon\-animated\-([\d\w]+)/);
|
||||
icon.removeClass($match[0]);
|
||||
$(this).off('click');
|
||||
var icon = $(this).find('[class*="icon-animated-"]').eq(0);
|
||||
var $match = icon.attr('class').match(/icon\-animated\-([\d\w]+)/);
|
||||
icon.removeClass($match[0]);
|
||||
$(this).off('click');
|
||||
});
|
||||
|
||||
$('.nav-list .badge[title],.nav-list .label[title]').tooltip({'placement':'right'});
|
||||
@@ -89,73 +89,73 @@ ace.general_things = function($) {
|
||||
//simple settings
|
||||
|
||||
$('#ace-settings-btn').on(ace.click_event, function(){
|
||||
$(this).toggleClass('open');
|
||||
$('#ace-settings-box').toggleClass('open');
|
||||
$(this).toggleClass('open');
|
||||
$('#ace-settings-box').toggleClass('open');
|
||||
});
|
||||
|
||||
|
||||
$('#ace-settings-navbar').on('click', function(){
|
||||
ace.settings.navbar_fixed(this.checked);//@ ace-extra.js
|
||||
ace.settings.navbar_fixed(this.checked);//@ ace-extra.js
|
||||
}).each(function(){this.checked = ace.settings.is('navbar', 'fixed')})
|
||||
|
||||
$('#ace-settings-sidebar').on('click', function(){
|
||||
ace.settings.sidebar_fixed(this.checked);//@ ace-extra.js
|
||||
ace.settings.sidebar_fixed(this.checked);//@ ace-extra.js
|
||||
}).each(function(){this.checked = ace.settings.is('sidebar', 'fixed')})
|
||||
|
||||
$('#ace-settings-breadcrumbs').on('click', function(){
|
||||
ace.settings.breadcrumbs_fixed(this.checked);//@ ace-extra.js
|
||||
ace.settings.breadcrumbs_fixed(this.checked);//@ ace-extra.js
|
||||
}).each(function(){this.checked = ace.settings.is('breadcrumbs', 'fixed')})
|
||||
|
||||
$('#ace-settings-add-container').on('click', function(){
|
||||
ace.settings.main_container_fixed(this.checked);//@ ace-extra.js
|
||||
ace.settings.main_container_fixed(this.checked);//@ ace-extra.js
|
||||
}).each(function(){this.checked = ace.settings.is('main-container', 'fixed')})
|
||||
|
||||
//Switching to RTL (right to left) Mode
|
||||
$('#ace-settings-rtl').removeAttr('checked').on('click', function(){
|
||||
ace.switch_direction(jQuery);
|
||||
ace.switch_direction(jQuery);
|
||||
});
|
||||
|
||||
|
||||
$('#btn-scroll-up').on(ace.click_event, function(){
|
||||
var duration = Math.min(400, Math.max(100, parseInt($('html').scrollTop() / 3)));
|
||||
$('html,body').animate({scrollTop: 0}, duration);
|
||||
return false;
|
||||
var duration = Math.min(400, Math.max(100, parseInt($('html').scrollTop() / 3)));
|
||||
$('html,body').animate({scrollTop: 0}, duration);
|
||||
return false;
|
||||
});
|
||||
|
||||
try {
|
||||
$('#skin-colorpicker').ace_colorpicker();
|
||||
$('#skin-colorpicker').ace_colorpicker();
|
||||
} catch(e) {}
|
||||
|
||||
$('#skin-colorpicker').on('change', function(){
|
||||
var skin_class = $(this).find('option:selected').data('skin');
|
||||
var skin_class = $(this).find('option:selected').data('skin');
|
||||
|
||||
var body = $(document.body);
|
||||
body.removeClass('skin-1 skin-2 skin-3');
|
||||
var body = $(document.body);
|
||||
body.removeClass('skin-1 skin-2 skin-3');
|
||||
|
||||
|
||||
if(skin_class != 'default') body.addClass(skin_class);
|
||||
if(skin_class != 'default') body.addClass(skin_class);
|
||||
|
||||
if(skin_class == 'skin-1') {
|
||||
$('.ace-nav > li.grey').addClass('dark');
|
||||
}
|
||||
else {
|
||||
$('.ace-nav > li.grey').removeClass('dark');
|
||||
}
|
||||
if(skin_class == 'skin-1') {
|
||||
$('.ace-nav > li.grey').addClass('dark');
|
||||
}
|
||||
else {
|
||||
$('.ace-nav > li.grey').removeClass('dark');
|
||||
}
|
||||
|
||||
if(skin_class == 'skin-2') {
|
||||
$('.ace-nav > li').addClass('no-border margin-1');
|
||||
$('.ace-nav > li:not(:last-child)').addClass('light-pink').find('> a > [class*="icon-"]').addClass('pink').end().eq(0).find('.badge').addClass('badge-warning');
|
||||
}
|
||||
else {
|
||||
$('.ace-nav > li').removeClass('no-border margin-1');
|
||||
$('.ace-nav > li:not(:last-child)').removeClass('light-pink').find('> a > [class*="icon-"]').removeClass('pink').end().eq(0).find('.badge').removeClass('badge-warning');
|
||||
}
|
||||
if(skin_class == 'skin-2') {
|
||||
$('.ace-nav > li').addClass('no-border margin-1');
|
||||
$('.ace-nav > li:not(:last-child)').addClass('light-pink').find('> a > [class*="icon-"]').addClass('pink').end().eq(0).find('.badge').addClass('badge-warning');
|
||||
}
|
||||
else {
|
||||
$('.ace-nav > li').removeClass('no-border margin-1');
|
||||
$('.ace-nav > li:not(:last-child)').removeClass('light-pink').find('> a > [class*="icon-"]').removeClass('pink').end().eq(0).find('.badge').removeClass('badge-warning');
|
||||
}
|
||||
|
||||
if(skin_class == 'skin-3') {
|
||||
$('.ace-nav > li.grey').addClass('red').find('.badge').addClass('badge-yellow');
|
||||
} else {
|
||||
$('.ace-nav > li.grey').removeClass('red').find('.badge').removeClass('badge-yellow');
|
||||
}
|
||||
if(skin_class == 'skin-3') {
|
||||
$('.ace-nav > li.grey').addClass('red').find('.badge').addClass('badge-yellow');
|
||||
} else {
|
||||
$('.ace-nav > li.grey').removeClass('red').find('.badge').removeClass('badge-yellow');
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
@@ -163,224 +163,224 @@ ace.general_things = function($) {
|
||||
|
||||
|
||||
ace.widget_boxes = function($) {
|
||||
$(document).on('hide.bs.collapse show.bs.collapse', function (ev) {
|
||||
var hidden_id = ev.target.getAttribute('id')
|
||||
$('[href*="#'+ hidden_id+'"]').find('[class*="icon-"]').each(function(){
|
||||
var $icon = $(this)
|
||||
$(document).on('hide.bs.collapse show.bs.collapse', function (ev) {
|
||||
var hidden_id = ev.target.getAttribute('id')
|
||||
$('[href*="#'+ hidden_id+'"]').find('[class*="icon-"]').each(function(){
|
||||
var $icon = $(this)
|
||||
|
||||
var $match
|
||||
var $icon_down = null
|
||||
var $icon_up = null
|
||||
if( ($icon_down = $icon.attr('data-icon-show')) ) {
|
||||
$icon_up = $icon.attr('data-icon-hide')
|
||||
}
|
||||
else if( $match = $icon.attr('class').match(/icon\-(.*)\-(up|down)/) ) {
|
||||
$icon_down = 'icon-'+$match[1]+'-down'
|
||||
$icon_up = 'icon-'+$match[1]+'-up'
|
||||
}
|
||||
var $match
|
||||
var $icon_down = null
|
||||
var $icon_up = null
|
||||
if( ($icon_down = $icon.attr('data-icon-show')) ) {
|
||||
$icon_up = $icon.attr('data-icon-hide')
|
||||
}
|
||||
else if( $match = $icon.attr('class').match(/icon\-(.*)\-(up|down)/) ) {
|
||||
$icon_down = 'icon-'+$match[1]+'-down'
|
||||
$icon_up = 'icon-'+$match[1]+'-up'
|
||||
}
|
||||
|
||||
if($icon_down) {
|
||||
if(ev.type == 'show') $icon.removeClass($icon_down).addClass($icon_up)
|
||||
else $icon.removeClass($icon_up).addClass($icon_down)
|
||||
|
||||
return false;//ignore other icons that match, one is enough
|
||||
}
|
||||
if($icon_down) {
|
||||
if(ev.type == 'show') $icon.removeClass($icon_down).addClass($icon_up)
|
||||
else $icon.removeClass($icon_up).addClass($icon_down)
|
||||
|
||||
return false;//ignore other icons that match, one is enough
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$(document).on('click.ace.widget', '[data-action]', function (ev) {
|
||||
ev.preventDefault();
|
||||
$(document).on('click.ace.widget', '[data-action]', function (ev) {
|
||||
ev.preventDefault();
|
||||
|
||||
var $this = $(this);
|
||||
var $action = $this.data('action');
|
||||
var $box = $this.closest('.widget-box');
|
||||
var $this = $(this);
|
||||
var $action = $this.data('action');
|
||||
var $box = $this.closest('.widget-box');
|
||||
|
||||
if($box.hasClass('ui-sortable-helper')) return;
|
||||
if($box.hasClass('ui-sortable-helper')) return;
|
||||
|
||||
if($action == 'collapse') {
|
||||
var event_name = $box.hasClass('collapsed') ? 'show' : 'hide';
|
||||
var event_complete_name = event_name == 'show' ? 'shown' : 'hidden';
|
||||
if($action == 'collapse') {
|
||||
var event_name = $box.hasClass('collapsed') ? 'show' : 'hide';
|
||||
var event_complete_name = event_name == 'show' ? 'shown' : 'hidden';
|
||||
|
||||
|
||||
var event
|
||||
$box.trigger(event = $.Event(event_name+'.ace.widget'))
|
||||
if (event.isDefaultPrevented()) return
|
||||
|
||||
var $body = $box.find('.widget-body');
|
||||
var $icon = $this.find('[class*=icon-]').eq(0);
|
||||
var $match = $icon.attr('class').match(/icon\-(.*)\-(up|down)/);
|
||||
var $icon_down = 'icon-'+$match[1]+'-down';
|
||||
var $icon_up = 'icon-'+$match[1]+'-up';
|
||||
|
||||
var $body_inner = $body.find('.widget-body-inner')
|
||||
if($body_inner.length == 0) {
|
||||
$body = $body.wrapInner('<div class="widget-body-inner"></div>').find(':first-child').eq(0);
|
||||
} else $body = $body_inner.eq(0);
|
||||
|
||||
var event
|
||||
$box.trigger(event = $.Event(event_name+'.ace.widget'))
|
||||
if (event.isDefaultPrevented()) return
|
||||
|
||||
var $body = $box.find('.widget-body');
|
||||
var $icon = $this.find('[class*=icon-]').eq(0);
|
||||
var $match = $icon.attr('class').match(/icon\-(.*)\-(up|down)/);
|
||||
var $icon_down = 'icon-'+$match[1]+'-down';
|
||||
var $icon_up = 'icon-'+$match[1]+'-up';
|
||||
|
||||
var $body_inner = $body.find('.widget-body-inner')
|
||||
if($body_inner.length == 0) {
|
||||
$body = $body.wrapInner('<div class="widget-body-inner"></div>').find(':first-child').eq(0);
|
||||
} else $body = $body_inner.eq(0);
|
||||
|
||||
|
||||
var expandSpeed = 300;
|
||||
var collapseSpeed = 200;
|
||||
var expandSpeed = 300;
|
||||
var collapseSpeed = 200;
|
||||
|
||||
if( event_name == 'show' ) {
|
||||
if($icon) $icon.addClass($icon_up).removeClass($icon_down);
|
||||
$box.removeClass('collapsed');
|
||||
$body.slideUp(0 , function(){$body.slideDown(expandSpeed, function(){$box.trigger(event = $.Event(event_complete_name+'.ace.widget'))})});
|
||||
}
|
||||
else {
|
||||
if($icon) $icon.addClass($icon_down).removeClass($icon_up);
|
||||
$body.slideUp(collapseSpeed, function(){$box.addClass('collapsed');$box.trigger(event = $.Event(event_complete_name+'.ace.widget'))});
|
||||
}
|
||||
if( event_name == 'show' ) {
|
||||
if($icon) $icon.addClass($icon_up).removeClass($icon_down);
|
||||
$box.removeClass('collapsed');
|
||||
$body.slideUp(0 , function(){$body.slideDown(expandSpeed, function(){$box.trigger(event = $.Event(event_complete_name+'.ace.widget'))})});
|
||||
}
|
||||
else {
|
||||
if($icon) $icon.addClass($icon_down).removeClass($icon_up);
|
||||
$body.slideUp(collapseSpeed, function(){$box.addClass('collapsed');$box.trigger(event = $.Event(event_complete_name+'.ace.widget'))});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if($action == 'close') {
|
||||
var event
|
||||
$box.trigger(event = $.Event('close.ace.widget'))
|
||||
if (event.isDefaultPrevented()) return
|
||||
|
||||
var closeSpeed = parseInt($this.data('close-speed')) || 300;
|
||||
$box.hide(closeSpeed , function(){$box.trigger(event = $.Event('closed.ace.widget'));$box.remove();});
|
||||
}
|
||||
else if($action == 'reload') {
|
||||
var event
|
||||
$box.trigger(event = $.Event('reload.ace.widget'))
|
||||
if (event.isDefaultPrevented()) return
|
||||
|
||||
}
|
||||
else if($action == 'close') {
|
||||
var event
|
||||
$box.trigger(event = $.Event('close.ace.widget'))
|
||||
if (event.isDefaultPrevented()) return
|
||||
|
||||
var closeSpeed = parseInt($this.data('close-speed')) || 300;
|
||||
$box.hide(closeSpeed , function(){$box.trigger(event = $.Event('closed.ace.widget'));$box.remove();});
|
||||
}
|
||||
else if($action == 'reload') {
|
||||
var event
|
||||
$box.trigger(event = $.Event('reload.ace.widget'))
|
||||
if (event.isDefaultPrevented()) return
|
||||
|
||||
$this.blur();
|
||||
$this.blur();
|
||||
|
||||
var $remove = false;
|
||||
if($box.css('position') == 'static') {$remove = true; $box.addClass('position-relative');}
|
||||
$box.append('<div class="widget-box-overlay"><i class="icon-spinner icon-spin icon-2x white"></i></div>');
|
||||
|
||||
$box.one('reloaded.ace.widget', function() {
|
||||
$box.find('.widget-box-overlay').remove();
|
||||
if($remove) $box.removeClass('position-relative');
|
||||
});
|
||||
var $remove = false;
|
||||
if($box.css('position') == 'static') {$remove = true; $box.addClass('position-relative');}
|
||||
$box.append('<div class="widget-box-overlay"><i class="icon-spinner icon-spin icon-2x white"></i></div>');
|
||||
|
||||
$box.one('reloaded.ace.widget', function() {
|
||||
$box.find('.widget-box-overlay').remove();
|
||||
if($remove) $box.removeClass('position-relative');
|
||||
});
|
||||
|
||||
}
|
||||
else if($action == 'settings') {
|
||||
var event = $.Event('settings.ace.widget')
|
||||
$box.trigger(event)
|
||||
}
|
||||
}
|
||||
else if($action == 'settings') {
|
||||
var event = $.Event('settings.ace.widget')
|
||||
$box.trigger(event)
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
ace.widget_reload_handler = function($) {
|
||||
//***default action for reload in this demo
|
||||
//you should remove this and add your own handler for each specific .widget-box
|
||||
//when data is finished loading or processing is done you can call $box.trigger('reloaded.ace.widget')
|
||||
$(document).on('reload.ace.widget', '.widget-box', function (ev) {
|
||||
var $box = $(this);
|
||||
//trigger the reloaded event after 1-2 seconds
|
||||
setTimeout(function() {
|
||||
$box.trigger('reloaded.ace.widget');
|
||||
}, parseInt(Math.random() * 1000 + 1000));
|
||||
});
|
||||
|
||||
|
||||
//you may want to do something like this:
|
||||
/**
|
||||
$('#my-widget-box').on('reload.ace.widget', function(){
|
||||
//load new data
|
||||
//when finished trigger "reloaded"
|
||||
$(this).trigger('reloaded.ace.widget');
|
||||
});
|
||||
*/
|
||||
//***default action for reload in this demo
|
||||
//you should remove this and add your own handler for each specific .widget-box
|
||||
//when data is finished loading or processing is done you can call $box.trigger('reloaded.ace.widget')
|
||||
$(document).on('reload.ace.widget', '.widget-box', function (ev) {
|
||||
var $box = $(this);
|
||||
//trigger the reloaded event after 1-2 seconds
|
||||
setTimeout(function() {
|
||||
$box.trigger('reloaded.ace.widget');
|
||||
}, parseInt(Math.random() * 1000 + 1000));
|
||||
});
|
||||
|
||||
|
||||
//you may want to do something like this:
|
||||
/**
|
||||
$('#my-widget-box').on('reload.ace.widget', function(){
|
||||
//load new data
|
||||
//when finished trigger "reloaded"
|
||||
$(this).trigger('reloaded.ace.widget');
|
||||
});
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
|
||||
//search box's dropdown autocomplete
|
||||
ace.enable_search_ahead = function($) {
|
||||
ace.variable_US_STATES = ["Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida","Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana","Maine","Maryland","Massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana","Nebraska","Nevada","New Hampshire","New Jersey","New Mexico","New York","North Dakota","North Carolina","Ohio","Oklahoma","Oregon","Pennsylvania","Rhode Island","South Carolina","South Dakota","Tennessee","Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming"]
|
||||
|
||||
try {
|
||||
$('#nav-search-input').typeahead({
|
||||
source: ace.variable_US_STATES,
|
||||
updater:function (item) {
|
||||
$('#nav-search-input').focus();
|
||||
return item;
|
||||
}
|
||||
});
|
||||
} catch(e) {}
|
||||
ace.variable_US_STATES = ["Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida","Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana","Maine","Maryland","Massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana","Nebraska","Nevada","New Hampshire","New Jersey","New Mexico","New York","North Dakota","North Carolina","Ohio","Oklahoma","Oregon","Pennsylvania","Rhode Island","South Carolina","South Dakota","Tennessee","Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming"]
|
||||
|
||||
try {
|
||||
$('#nav-search-input').typeahead({
|
||||
source: ace.variable_US_STATES,
|
||||
updater:function (item) {
|
||||
$('#nav-search-input').focus();
|
||||
return item;
|
||||
}
|
||||
});
|
||||
} catch(e) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
ace.switch_direction = function($) {
|
||||
var $body = $(document.body);
|
||||
$body
|
||||
.toggleClass('rtl')
|
||||
//toggle pull-right class on dropdown-menu
|
||||
.find('.dropdown-menu:not(.datepicker-dropdown,.colorpicker)').toggleClass('pull-right')
|
||||
.end()
|
||||
//swap pull-left & pull-right
|
||||
.find('.pull-right:not(.dropdown-menu,blockquote,.profile-skills .pull-right)').removeClass('pull-right').addClass('tmp-rtl-pull-right')
|
||||
.end()
|
||||
.find('.pull-left:not(.dropdown-submenu,.profile-skills .pull-left)').removeClass('pull-left').addClass('pull-right')
|
||||
.end()
|
||||
.find('.tmp-rtl-pull-right').removeClass('tmp-rtl-pull-right').addClass('pull-left')
|
||||
.end()
|
||||
|
||||
.find('.chosen-container').toggleClass('chosen-rtl')
|
||||
.end()
|
||||
var $body = $(document.body);
|
||||
$body
|
||||
.toggleClass('rtl')
|
||||
//toggle pull-right class on dropdown-menu
|
||||
.find('.dropdown-menu:not(.datepicker-dropdown,.colorpicker)').toggleClass('pull-right')
|
||||
.end()
|
||||
//swap pull-left & pull-right
|
||||
.find('.pull-right:not(.dropdown-menu,blockquote,.profile-skills .pull-right)').removeClass('pull-right').addClass('tmp-rtl-pull-right')
|
||||
.end()
|
||||
.find('.pull-left:not(.dropdown-submenu,.profile-skills .pull-left)').removeClass('pull-left').addClass('pull-right')
|
||||
.end()
|
||||
.find('.tmp-rtl-pull-right').removeClass('tmp-rtl-pull-right').addClass('pull-left')
|
||||
.end()
|
||||
|
||||
.find('.chosen-container').toggleClass('chosen-rtl')
|
||||
.end()
|
||||
|
||||
function swap_classes(class1, class2) {
|
||||
$body
|
||||
.find('.'+class1).removeClass(class1).addClass('tmp-rtl-'+class1)
|
||||
.end()
|
||||
.find('.'+class2).removeClass(class2).addClass(class1)
|
||||
.end()
|
||||
.find('.tmp-rtl-'+class1).removeClass('tmp-rtl-'+class1).addClass(class2)
|
||||
}
|
||||
function swap_styles(style1, style2, elements) {
|
||||
elements.each(function(){
|
||||
var e = $(this);
|
||||
var tmp = e.css(style2);
|
||||
e.css(style2 , e.css(style1));
|
||||
e.css(style1 , tmp);
|
||||
});
|
||||
}
|
||||
function swap_classes(class1, class2) {
|
||||
$body
|
||||
.find('.'+class1).removeClass(class1).addClass('tmp-rtl-'+class1)
|
||||
.end()
|
||||
.find('.'+class2).removeClass(class2).addClass(class1)
|
||||
.end()
|
||||
.find('.tmp-rtl-'+class1).removeClass('tmp-rtl-'+class1).addClass(class2)
|
||||
}
|
||||
function swap_styles(style1, style2, elements) {
|
||||
elements.each(function(){
|
||||
var e = $(this);
|
||||
var tmp = e.css(style2);
|
||||
e.css(style2 , e.css(style1));
|
||||
e.css(style1 , tmp);
|
||||
});
|
||||
}
|
||||
|
||||
swap_classes('align-left', 'align-right');
|
||||
swap_classes('no-padding-left', 'no-padding-right');
|
||||
swap_classes('arrowed', 'arrowed-right');
|
||||
swap_classes('arrowed-in', 'arrowed-in-right');
|
||||
swap_classes('messagebar-item-left', 'messagebar-item-right');//for inbox page
|
||||
swap_classes('align-left', 'align-right');
|
||||
swap_classes('no-padding-left', 'no-padding-right');
|
||||
swap_classes('arrowed', 'arrowed-right');
|
||||
swap_classes('arrowed-in', 'arrowed-in-right');
|
||||
swap_classes('messagebar-item-left', 'messagebar-item-right');//for inbox page
|
||||
|
||||
|
||||
//redraw the traffic pie chart on homepage with a different parameter
|
||||
var placeholder = $('#piechart-placeholder');
|
||||
if(placeholder.size() > 0) {
|
||||
var pos = $(document.body).hasClass('rtl') ? 'nw' : 'ne';//draw on north-west or north-east?
|
||||
placeholder.data('draw').call(placeholder.get(0) , placeholder, placeholder.data('chart'), pos);
|
||||
}
|
||||
//redraw the traffic pie chart on homepage with a different parameter
|
||||
var placeholder = $('#piechart-placeholder');
|
||||
if(placeholder.size() > 0) {
|
||||
var pos = $(document.body).hasClass('rtl') ? 'nw' : 'ne';//draw on north-west or north-east?
|
||||
placeholder.data('draw').call(placeholder.get(0) , placeholder, placeholder.data('chart'), pos);
|
||||
}
|
||||
};
|
||||
|
||||
jQuery(function($) {
|
||||
//ace.click_event defined in ace-elements.js
|
||||
ace.handle_side_menu(jQuery);
|
||||
//ace.click_event defined in ace-elements.js
|
||||
ace.handle_side_menu(jQuery);
|
||||
|
||||
ace.enable_search_ahead(jQuery);
|
||||
ace.enable_search_ahead(jQuery);
|
||||
|
||||
ace.general_things(jQuery);//and settings
|
||||
ace.general_things(jQuery);//and settings
|
||||
|
||||
ace.widget_boxes(jQuery);
|
||||
ace.widget_reload_handler(jQuery);//this is for demo only, you can remove and have your own function, please see examples/widget.html
|
||||
ace.widget_boxes(jQuery);
|
||||
ace.widget_reload_handler(jQuery);//this is for demo only, you can remove and have your own function, please see examples/widget.html
|
||||
|
||||
/**
|
||||
//make sidebar scrollbar when it is fixed and some parts of it is out of view
|
||||
//>> you should include jquery-ui and slimscroll javascript files in your file
|
||||
//>> you can call this function when sidebar is clicked to be fixed
|
||||
$('.nav-list').slimScroll({
|
||||
height: '400px',
|
||||
distance:0,
|
||||
size : '6px'
|
||||
});
|
||||
*/
|
||||
/**
|
||||
//make sidebar scrollbar when it is fixed and some parts of it is out of view
|
||||
//>> you should include jquery-ui and slimscroll javascript files in your file
|
||||
//>> you can call this function when sidebar is clicked to be fixed
|
||||
$('.nav-list').slimScroll({
|
||||
height: '400px',
|
||||
distance:0,
|
||||
size : '6px'
|
||||
});
|
||||
*/
|
||||
});
|
||||
|
||||
|
||||
6938
static/js/lib/backbone-orm.js
Normal file
6938
static/js/lib/backbone-orm.js
Normal file
File diff suppressed because it is too large
Load Diff
3
static/js/lib/backbone-relational.js
Normal file
3
static/js/lib/backbone-relational.js
Normal file
@@ -0,0 +1,3 @@
|
||||
/**
|
||||
* Created by fergalm on 11/12/13.
|
||||
*/
|
||||
574
static/js/lib/backbone.associations.js
Normal file
574
static/js/lib/backbone.associations.js
Normal file
@@ -0,0 +1,574 @@
|
||||
//
|
||||
// Backbone-associations.js 0.5.4
|
||||
//
|
||||
// (c) 2013 Dhruva Ray, Jaynti Kanani, Persistent Systems Ltd.
|
||||
// Backbone-associations may be freely distributed under the MIT license.
|
||||
// For all details and documentation:
|
||||
// https://github.com/dhruvaray/backbone-associations/
|
||||
//
|
||||
|
||||
// Initial Setup
|
||||
// --------------
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
// Save a reference to the global object (`window` in the browser, `exports`
|
||||
// on the server).
|
||||
var root = this;
|
||||
|
||||
// The top-level namespace. All public Backbone classes and modules will be attached to this.
|
||||
// Exported for the browser and CommonJS.
|
||||
var _, Backbone, BackboneModel, BackboneCollection, ModelProto,
|
||||
CollectionProto, defaultEvents, AssociatedModel, pathChecker,
|
||||
collectionEvents, delimiters, pathSeparator;
|
||||
|
||||
if (typeof exports !== 'undefined') {
|
||||
_ = require('underscore');
|
||||
Backbone = require('backbone');
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = Backbone;
|
||||
}
|
||||
exports = Backbone;
|
||||
} else {
|
||||
_ = root._;
|
||||
Backbone = root.Backbone;
|
||||
}
|
||||
// Create local reference `Model` prototype.
|
||||
BackboneModel = Backbone.Model;
|
||||
BackboneCollection = Backbone.Collection;
|
||||
ModelProto = BackboneModel.prototype;
|
||||
CollectionProto = BackboneCollection.prototype;
|
||||
|
||||
// Built-in Backbone `events`.
|
||||
defaultEvents = ["change", "add", "remove", "reset", "sort", "destroy"];
|
||||
collectionEvents = ["reset", "sort"];
|
||||
|
||||
Backbone.Associations = {
|
||||
VERSION: "0.5.4"
|
||||
};
|
||||
|
||||
// Define `getter` and `setter` for `separator`
|
||||
var getSeparator = function() {
|
||||
return pathSeparator;
|
||||
};
|
||||
// Define `setSeperator`
|
||||
var setSeparator = function(value) {
|
||||
if (!_.isString(value) || _.size(value) < 1) {
|
||||
value = ".";
|
||||
}
|
||||
// set private properties
|
||||
pathSeparator = value;
|
||||
pathChecker = new RegExp("[\\" + pathSeparator + "\\[\\]]+", "g");
|
||||
delimiters = new RegExp("[^\\" + pathSeparator + "\\[\\]]+", "g");
|
||||
};
|
||||
|
||||
try {
|
||||
// Define `SEPERATOR` property to Backbone.Associations
|
||||
Object.defineProperty(Backbone.Associations, 'SEPARATOR', {
|
||||
enumerable: true,
|
||||
get: getSeparator,
|
||||
set: setSeparator
|
||||
});
|
||||
} catch (e) {}
|
||||
|
||||
// Backbone.AssociatedModel
|
||||
// --------------
|
||||
|
||||
//Add `Many` and `One` relations to Backbone Object.
|
||||
Backbone.Associations.Many = Backbone.Many = "Many";
|
||||
Backbone.Associations.One = Backbone.One = "One";
|
||||
Backbone.Associations.Self = Backbone.Self = "Self";
|
||||
// Set default separator
|
||||
Backbone.Associations.SEPARATOR = ".";
|
||||
Backbone.Associations.getSeparator = getSeparator;
|
||||
Backbone.Associations.setSeparator = setSeparator;
|
||||
setSeparator();
|
||||
// Define `AssociatedModel` (Extends Backbone.Model).
|
||||
AssociatedModel = Backbone.AssociatedModel = Backbone.Associations.AssociatedModel = BackboneModel.extend({
|
||||
// Define relations with Associated Model.
|
||||
relations:undefined,
|
||||
// Define `Model` property which can keep track of already fired `events`,
|
||||
// and prevent redundant event to be triggered in case of cyclic model graphs.
|
||||
_proxyCalls:undefined,
|
||||
|
||||
// Get the value of an attribute.
|
||||
get:function (attr) {
|
||||
var obj = ModelProto.get.call(this, attr);
|
||||
return obj ? obj : this._getAttr.apply(this, arguments);
|
||||
},
|
||||
|
||||
// Set a hash of model attributes on the Backbone Model.
|
||||
set:function (key, value, options) {
|
||||
var attributes, result;
|
||||
// Duplicate backbone's behavior to allow separate key/value parameters,
|
||||
// instead of a single 'attributes' object.
|
||||
if (_.isObject(key) || key == null) {
|
||||
attributes = key;
|
||||
options = value;
|
||||
} else {
|
||||
attributes = {};
|
||||
attributes[key] = value;
|
||||
}
|
||||
result = this._set(attributes, options);
|
||||
// Trigger events which have been blocked until the entire object graph is updated.
|
||||
this._processPendingEvents();
|
||||
return result;
|
||||
|
||||
},
|
||||
|
||||
// Works with an attribute hash and options + fully qualified paths
|
||||
_set:function (attributes, options) {
|
||||
var attr, modelMap, modelId, obj, result = this;
|
||||
if (!attributes) return this;
|
||||
for (attr in attributes) {
|
||||
//Create a map for each unique object whose attributes we want to set
|
||||
modelMap || (modelMap = {});
|
||||
if (attr.match(pathChecker)) {
|
||||
var pathTokens = getPathArray(attr), initials = _.initial(pathTokens),
|
||||
last = pathTokens[pathTokens.length - 1],
|
||||
parentModel = this.get(initials);
|
||||
if (parentModel instanceof AssociatedModel) {
|
||||
obj = modelMap[parentModel.cid] || (modelMap[parentModel.cid] = {'model':parentModel, 'data':{}});
|
||||
obj.data[last] = attributes[attr];
|
||||
}
|
||||
} else {
|
||||
obj = modelMap[this.cid] || (modelMap[this.cid] = {'model':this, 'data':{}});
|
||||
obj.data[attr] = attributes[attr];
|
||||
}
|
||||
}
|
||||
|
||||
if (modelMap) {
|
||||
for (modelId in modelMap) {
|
||||
obj = modelMap[modelId];
|
||||
this._setAttr.call(obj.model, obj.data, options) || (result = false);
|
||||
|
||||
}
|
||||
} else {
|
||||
result = this._setAttr.call(this, attributes, options);
|
||||
}
|
||||
return result;
|
||||
|
||||
},
|
||||
|
||||
// Set a hash of model attributes on the object,
|
||||
// fire Backbone `event` with options.
|
||||
// It maintains relations between models during the set operation.
|
||||
// It also bubbles up child events to the parent.
|
||||
_setAttr:function (attributes, options) {
|
||||
var attr;
|
||||
// Extract attributes and options.
|
||||
options || (options = {});
|
||||
if (options.unset) for (attr in attributes) attributes[attr] = void 0;
|
||||
this.parents = this.parents || [];
|
||||
|
||||
if (this.relations) {
|
||||
// Iterate over `this.relations` and `set` model and collection values
|
||||
// if `relations` are available.
|
||||
_.each(this.relations, function (relation) {
|
||||
var relationKey = relation.key,
|
||||
relatedModel = relation.relatedModel,
|
||||
collectionType = relation.collectionType,
|
||||
map = relation.map,
|
||||
currVal = this.attributes[relationKey],
|
||||
idKey = currVal && currVal.idAttribute,
|
||||
val, relationOptions, data, relationValue, newCtx = false;
|
||||
|
||||
// Call function if relatedModel is implemented as a function
|
||||
if (relatedModel && !(relatedModel.prototype instanceof BackboneModel))
|
||||
relatedModel = _.isFunction(relatedModel) ?
|
||||
relatedModel.call(this, relation, attributes) :
|
||||
relatedModel;
|
||||
|
||||
// Get class if relation and map is stored as a string.
|
||||
if (relatedModel && _.isString(relatedModel)) {
|
||||
relatedModel = (relatedModel === Backbone.Self) ? this.constructor : map2Scope(relatedModel);
|
||||
}
|
||||
collectionType && _.isString(collectionType) && (collectionType = map2Scope(collectionType));
|
||||
map && _.isString(map) && (map = map2Scope(map));
|
||||
// Merge in `options` specific to this relation.
|
||||
relationOptions = relation.options ? _.extend({}, relation.options, options) : options;
|
||||
|
||||
if ((!relatedModel) && (!collectionType))
|
||||
throw new Error('specify either a relatedModel or collectionType');
|
||||
|
||||
if (attributes[relationKey]) {
|
||||
// Get value of attribute with relation key in `val`.
|
||||
val = _.result(attributes, relationKey);
|
||||
// Map `val` if a transformation function is provided.
|
||||
val = map ? map.call(this, val, collectionType ? collectionType : relatedModel) : val;
|
||||
|
||||
// If `relation.type` is `Backbone.Many`,
|
||||
// Create `Backbone.Collection` with passed data and perform Backbone `set`.
|
||||
if (relation.type === Backbone.Many) {
|
||||
// `collectionType` of defined `relation` should be instance of `Backbone.Collection`.
|
||||
if (collectionType && !collectionType.prototype instanceof BackboneCollection) {
|
||||
throw new Error('collectionType must inherit from Backbone.Collection');
|
||||
}
|
||||
|
||||
if (currVal) {
|
||||
// Setting this flag will prevent events from firing immediately. That way clients
|
||||
// will not get events until the entire object graph is updated.
|
||||
currVal._deferEvents = true;
|
||||
|
||||
// Use Backbone.Collection's `reset` or smart `set` method
|
||||
currVal[relationOptions.reset ? 'reset' : 'set'](
|
||||
val instanceof BackboneCollection ? val.models : val, relationOptions);
|
||||
|
||||
data = currVal;
|
||||
|
||||
} else {
|
||||
newCtx = true;
|
||||
|
||||
if (val instanceof BackboneCollection) {
|
||||
data = val;
|
||||
} else {
|
||||
data = collectionType ? new collectionType() : this._createCollection(relatedModel);
|
||||
data[relationOptions.reset ? 'reset' : 'set'](val, relationOptions);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (relation.type === Backbone.One) {
|
||||
|
||||
if (!relatedModel)
|
||||
throw new Error('specify a relatedModel for Backbone.One type');
|
||||
|
||||
if (!(relatedModel.prototype instanceof Backbone.AssociatedModel))
|
||||
throw new Error('specify an AssociatedModel for Backbone.One type');
|
||||
|
||||
data = val instanceof AssociatedModel ? val : new relatedModel(val, relationOptions);
|
||||
//Is the passed in data for the same key?
|
||||
if (currVal && data.attributes[idKey] &&
|
||||
currVal.attributes[idKey] === data.attributes[idKey]) {
|
||||
// Setting this flag will prevent events from firing immediately. That way clients
|
||||
// will not get events until the entire object graph is updated.
|
||||
currVal._deferEvents = true;
|
||||
// Perform the traditional `set` operation
|
||||
currVal._set(val instanceof AssociatedModel ? val.attributes : val, relationOptions);
|
||||
data = currVal;
|
||||
} else {
|
||||
newCtx = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new Error('type attribute must be specified and have the values Backbone.One or Backbone.Many');
|
||||
}
|
||||
|
||||
|
||||
attributes[relationKey] = data;
|
||||
relationValue = data;
|
||||
|
||||
// Add proxy events to respective parents.
|
||||
// Only add callback if not defined or new Ctx has been identified.
|
||||
if (newCtx || (relationValue && !relationValue._proxyCallback)) {
|
||||
relationValue._proxyCallback = function () {
|
||||
return this._bubbleEvent.call(this, relationKey, relationValue, arguments);
|
||||
};
|
||||
relationValue.on("all", relationValue._proxyCallback, this);
|
||||
}
|
||||
|
||||
}
|
||||
//Distinguish between the value of undefined versus a set no-op
|
||||
if (attributes.hasOwnProperty(relationKey)) {
|
||||
//Maintain reverse pointers - a.k.a parents
|
||||
var updated = attributes[relationKey];
|
||||
var original = this.attributes[relationKey];
|
||||
if (updated) {
|
||||
updated.parents = updated.parents || [];
|
||||
(_.indexOf(updated.parents, this) == -1) && updated.parents.push(this);
|
||||
} else if (original && original.parents.length > 0) { // New value is undefined
|
||||
original.parents = _.difference(original.parents, [this]);
|
||||
// Don't bubble to this parent anymore
|
||||
original._proxyCallback && original.off("all", original._proxyCallback, this);
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
// Return results for `BackboneModel.set`.
|
||||
return ModelProto.set.call(this, attributes, options);
|
||||
},
|
||||
// Bubble-up event to `parent` Model
|
||||
_bubbleEvent:function (relationKey, relationValue, eventArguments) {
|
||||
var args = eventArguments,
|
||||
opt = args[0].split(":"),
|
||||
eventType = opt[0],
|
||||
catch_all = args[0] == "nested-change",
|
||||
eventObject = args[1],
|
||||
colObject = args[2],
|
||||
indexEventObject = -1,
|
||||
_proxyCalls = relationValue._proxyCalls,
|
||||
cargs,
|
||||
eventPath,
|
||||
basecolEventPath,
|
||||
isDefaultEvent = _.indexOf(defaultEvents, eventType) !== -1;
|
||||
|
||||
//Short circuit the listen in to the nested-graph event
|
||||
if (catch_all) return;
|
||||
|
||||
// Change the event name to a fully qualified path.
|
||||
_.size(opt) > 1 && (eventPath = opt[1]);
|
||||
|
||||
if (_.indexOf(collectionEvents, eventType) !== -1) {
|
||||
colObject = eventObject;
|
||||
}
|
||||
|
||||
// Find the specific object in the collection which has changed.
|
||||
if (relationValue instanceof BackboneCollection && isDefaultEvent && eventObject) {
|
||||
var pathTokens = getPathArray(eventPath),
|
||||
initialTokens = _.initial(pathTokens), colModel;
|
||||
|
||||
colModel = relationValue.find(function (model) {
|
||||
if (eventObject === model) return true;
|
||||
if (!model) return false;
|
||||
var changedModel = model.get(initialTokens);
|
||||
|
||||
if ((changedModel instanceof AssociatedModel || changedModel instanceof BackboneCollection)
|
||||
&& eventObject === changedModel)
|
||||
return true;
|
||||
|
||||
changedModel = model.get(pathTokens);
|
||||
|
||||
if ((changedModel instanceof AssociatedModel || changedModel instanceof BackboneCollection)
|
||||
&& eventObject === changedModel)
|
||||
return true;
|
||||
|
||||
if (changedModel instanceof BackboneCollection && colObject
|
||||
&& colObject === changedModel)
|
||||
return true;
|
||||
});
|
||||
colModel && (indexEventObject = relationValue.indexOf(colModel));
|
||||
}
|
||||
|
||||
// Manipulate `eventPath`.
|
||||
eventPath = relationKey + ((indexEventObject !== -1 && (eventType === "change" || eventPath)) ?
|
||||
"[" + indexEventObject + "]" : "") + (eventPath ? pathSeparator + eventPath : "");
|
||||
|
||||
// Short circuit collection * events
|
||||
if (/\[\*\]/g.test(eventPath)) return this;
|
||||
basecolEventPath = eventPath.replace(/\[\d+\]/g, '[*]');
|
||||
|
||||
cargs = [];
|
||||
cargs.push.apply(cargs, args);
|
||||
cargs[0] = eventType + ":" + eventPath;
|
||||
|
||||
// If event has been already triggered as result of same source `eventPath`,
|
||||
// no need to re-trigger event to prevent cycle.
|
||||
_proxyCalls = relationValue._proxyCalls = (_proxyCalls || {});
|
||||
if (this._isEventAvailable.call(this, _proxyCalls, eventPath)) return this;
|
||||
|
||||
// Add `eventPath` in `_proxyCalls` to keep track of already triggered `event`.
|
||||
_proxyCalls[eventPath] = true;
|
||||
|
||||
// Set up previous attributes correctly.
|
||||
if ("change" === eventType) {
|
||||
this._previousAttributes[relationKey] = relationValue._previousAttributes;
|
||||
this.changed[relationKey] = relationValue;
|
||||
}
|
||||
|
||||
// Bubble up event to parent `model` with new changed arguments.
|
||||
this.trigger.apply(this, cargs);
|
||||
|
||||
//Only fire for change. Not change:attribute
|
||||
if ("change" === eventType && this.get(eventPath) != args[2]) {
|
||||
var ncargs = ["nested-change", eventPath, args[1]];
|
||||
args[2] && ncargs.push(args[2]); //args[2] will be options if present
|
||||
this.trigger.apply(this, ncargs);
|
||||
}
|
||||
|
||||
// Remove `eventPath` from `_proxyCalls`,
|
||||
// if `eventPath` and `_proxyCalls` are available,
|
||||
// which allow event to be triggered on for next operation of `set`.
|
||||
if (_proxyCalls && eventPath) delete _proxyCalls[eventPath];
|
||||
|
||||
// Create a collection modified event with wild-card
|
||||
if (eventPath !== basecolEventPath) {
|
||||
cargs[0] = eventType + ":" + basecolEventPath;
|
||||
this.trigger.apply(this, cargs);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
// Has event been fired from this source. Used to prevent event recursion in cyclic graphs
|
||||
_isEventAvailable:function (_proxyCalls, path) {
|
||||
return _.find(_proxyCalls, function (value, eventKey) {
|
||||
return path.indexOf(eventKey, path.length - eventKey.length) !== -1;
|
||||
});
|
||||
},
|
||||
|
||||
// Returns New `collection` of type `relation.relatedModel`.
|
||||
_createCollection:function (type) {
|
||||
var collection, relatedModel = type;
|
||||
_.isString(relatedModel) && (relatedModel = map2Scope(relatedModel));
|
||||
// Creates new `Backbone.Collection` and defines model class.
|
||||
if (relatedModel && (relatedModel.prototype instanceof AssociatedModel) || _.isFunction(relatedModel)) {
|
||||
collection = new BackboneCollection();
|
||||
collection.model = relatedModel;
|
||||
} else {
|
||||
throw new Error('type must inherit from Backbone.AssociatedModel');
|
||||
}
|
||||
return collection;
|
||||
},
|
||||
|
||||
// Process all pending events after the entire object graph has been updated
|
||||
_processPendingEvents:function () {
|
||||
if (!this._processedEvents) {
|
||||
this._processedEvents = true;
|
||||
|
||||
this._deferEvents = false;
|
||||
|
||||
// Trigger all pending events
|
||||
_.each(this._pendingEvents, function (e) {
|
||||
e.c.trigger.apply(e.c, e.a);
|
||||
});
|
||||
|
||||
this._pendingEvents = [];
|
||||
|
||||
// Traverse down the object graph and call process pending events on sub-trees
|
||||
_.each(this.relations, function (relation) {
|
||||
var val = this.attributes[relation.key];
|
||||
val && val._processPendingEvents();
|
||||
}, this);
|
||||
|
||||
delete this._processedEvents;
|
||||
}
|
||||
},
|
||||
|
||||
// Override trigger to defer events in the object graph.
|
||||
trigger:function (name) {
|
||||
// Defer event processing
|
||||
if (this._deferEvents) {
|
||||
this._pendingEvents = this._pendingEvents || [];
|
||||
// Maintain a queue of pending events to trigger after the entire object graph is updated.
|
||||
this._pendingEvents.push({c:this, a:arguments});
|
||||
} else {
|
||||
ModelProto.trigger.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
|
||||
// The JSON representation of the model.
|
||||
toJSON:function (options) {
|
||||
var json = {}, aJson;
|
||||
json[this.idAttribute] = this.id;
|
||||
if (!this.visited) {
|
||||
this.visited = true;
|
||||
// Get json representation from `BackboneModel.toJSON`.
|
||||
json = ModelProto.toJSON.apply(this, arguments);
|
||||
// If `this.relations` is defined, iterate through each `relation`
|
||||
// and added it's json representation to parents' json representation.
|
||||
if (this.relations) {
|
||||
_.each(this.relations, function (relation) {
|
||||
var attr = this.attributes[relation.key];
|
||||
if (attr) {
|
||||
aJson = attr.toJSON ? attr.toJSON(options) : attr;
|
||||
json[relation.key] = _.isArray(aJson) ? _.compact(aJson) : aJson;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
delete this.visited;
|
||||
}
|
||||
return json;
|
||||
},
|
||||
|
||||
// Create a new model with identical attributes to this one.
|
||||
clone:function () {
|
||||
return new this.constructor(this.toJSON());
|
||||
},
|
||||
|
||||
// Call this if you want to set an `AssociatedModel` to a falsy value like undefined/null directly.
|
||||
// Not calling this will leak memory and have wrong parents.
|
||||
// See test case "parent relations"
|
||||
cleanup:function () {
|
||||
_.each(this.relations, function (relation) {
|
||||
var val = this.attributes[relation.key];
|
||||
val && (val.parents = _.difference(val.parents, [this]));
|
||||
}, this);
|
||||
this.off();
|
||||
},
|
||||
|
||||
// Navigate the path to the leaf object in the path to query for the attribute value
|
||||
_getAttr:function (path) {
|
||||
|
||||
var result = this,
|
||||
//Tokenize the path
|
||||
attrs = getPathArray(path),
|
||||
key,
|
||||
i;
|
||||
if (_.size(attrs) < 1) return;
|
||||
for (i = 0; i < attrs.length; i++) {
|
||||
key = attrs[i];
|
||||
if (!result) break;
|
||||
//Navigate the path to get to the result
|
||||
result = result instanceof BackboneCollection
|
||||
? (isNaN(key) ? undefined : result.at(key))
|
||||
: result.attributes[key];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
// Tokenize the fully qualified event path
|
||||
var getPathArray = function (path) {
|
||||
if (path === '') return [''];
|
||||
return _.isString(path) ? (path.match(delimiters)) : path || [];
|
||||
};
|
||||
|
||||
var map2Scope = function (path) {
|
||||
return _.reduce(path.split(pathSeparator), function (memo, elem) {
|
||||
return memo[elem];
|
||||
}, root);
|
||||
};
|
||||
|
||||
//Infer the relation from the collection's parents and find the appropriate map for the passed in `models`
|
||||
var map2models = function (parents, target, models) {
|
||||
var relation, surrogate;
|
||||
//Iterate over collection's parents
|
||||
_.find(parents, function (parent) {
|
||||
//Iterate over relations
|
||||
relation = _.find(parent.relations, function (rel) {
|
||||
return parent.get(rel.key) === target;
|
||||
}, this);
|
||||
if (relation) {
|
||||
surrogate = parent;//surrogate for transformation
|
||||
return true;//break;
|
||||
}
|
||||
}, this);
|
||||
|
||||
//If we found a relation and it has a mapping function
|
||||
if (relation && relation.map) {
|
||||
return relation.map.call(surrogate, models, target);
|
||||
}
|
||||
return models;
|
||||
};
|
||||
|
||||
var proxies = {};
|
||||
// Proxy Backbone collection methods
|
||||
_.each(['set', 'remove', 'reset'], function (method) {
|
||||
proxies[method] = BackboneCollection.prototype[method];
|
||||
|
||||
CollectionProto[method] = function (models, options) {
|
||||
//Short-circuit if this collection doesn't hold `AssociatedModels`
|
||||
if (this.model.prototype instanceof AssociatedModel && this.parents) {
|
||||
//Find a map function if available and perform a transformation
|
||||
arguments[0] = map2models(this.parents, this, models);
|
||||
}
|
||||
return proxies[method].apply(this, arguments);
|
||||
}
|
||||
});
|
||||
|
||||
// Override trigger to defer events in the object graph.
|
||||
proxies['trigger'] = CollectionProto['trigger'];
|
||||
CollectionProto['trigger'] = function (name) {
|
||||
if (this._deferEvents) {
|
||||
this._pendingEvents = this._pendingEvents || [];
|
||||
// Maintain a queue of pending events to trigger after the entire object graph is updated.
|
||||
this._pendingEvents.push({c:this, a:arguments});
|
||||
} else {
|
||||
proxies['trigger'].apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
// Attach process pending event functionality on collections as well. Re-use from `AssociatedModel`
|
||||
CollectionProto._processPendingEvents = AssociatedModel.prototype._processPendingEvents;
|
||||
|
||||
|
||||
}).call(this);
|
||||
@@ -2001,7 +2001,7 @@ Marionette.AppRouter = Backbone.Router.extend({
|
||||
|
||||
constructor: function(options){
|
||||
Backbone.Router.prototype.constructor.apply(this, slice(arguments));
|
||||
|
||||
|
||||
this.options = options || {};
|
||||
|
||||
var appRoutes = Marionette.getOption(this, "appRoutes");
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
2458
static/js/lib/bootstrap-editable.js
vendored
2458
static/js/lib/bootstrap-editable.js
vendored
File diff suppressed because it is too large
Load Diff
398
static/js/lib/bootstrap-wysiwyg.js
vendored
398
static/js/lib/bootstrap-wysiwyg.js
vendored
@@ -2,205 +2,205 @@
|
||||
/*global jQuery, $, FileReader*/
|
||||
/*jslint browser:true*/
|
||||
(function ($) {
|
||||
'use strict';
|
||||
var readFileIntoDataUrl = function (fileInfo) {
|
||||
var loader = $.Deferred(),
|
||||
fReader = new FileReader();
|
||||
fReader.onload = function (e) {
|
||||
loader.resolve(e.target.result);
|
||||
};
|
||||
fReader.onerror = loader.reject;
|
||||
fReader.onprogress = loader.notify;
|
||||
fReader.readAsDataURL(fileInfo);
|
||||
return loader.promise();
|
||||
};
|
||||
$.fn.cleanHtml = function () {
|
||||
var html = $(this).html();
|
||||
return html && html.replace(/(<br>|\s|<div><br><\/div>| )*$/, '');
|
||||
};
|
||||
$.fn.wysiwyg = function (userOptions) {
|
||||
var editor = this,
|
||||
selectedRange,
|
||||
options,
|
||||
toolbarBtnSelector,
|
||||
updateToolbar = function () {
|
||||
if (options.activeToolbarClass) {
|
||||
$(options.toolbarSelector).find(toolbarBtnSelector).each(function () {
|
||||
try {
|
||||
var command = $(this).data(options.commandRole);
|
||||
if (document.queryCommandState(command)) {
|
||||
$(this).addClass(options.activeToolbarClass);
|
||||
} else {
|
||||
$(this).removeClass(options.activeToolbarClass);
|
||||
}
|
||||
} catch(e){}
|
||||
});
|
||||
}
|
||||
},
|
||||
execCommand = function (commandWithArgs, valueArg) {
|
||||
var commandArr = commandWithArgs.split(' '),
|
||||
command = commandArr.shift(),
|
||||
args = commandArr.join(' ') + (valueArg || '');
|
||||
document.execCommand(command, 0, args);
|
||||
updateToolbar();
|
||||
},
|
||||
bindHotkeys = function (hotKeys) {
|
||||
$.each(hotKeys, function (hotkey, command) {
|
||||
editor.keydown(hotkey, function (e) {
|
||||
if (editor.attr('contenteditable') && editor.is(':visible')) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
execCommand(command);
|
||||
}
|
||||
}).keyup(hotkey, function (e) {
|
||||
if (editor.attr('contenteditable') && editor.is(':visible')) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
getCurrentRange = function () {
|
||||
try {
|
||||
var sel = window.getSelection();
|
||||
if (sel.getRangeAt && sel.rangeCount) {
|
||||
return sel.getRangeAt(0);
|
||||
}
|
||||
} catch(e){}
|
||||
},
|
||||
saveSelection = function () {
|
||||
selectedRange = getCurrentRange();
|
||||
},
|
||||
restoreSelection = function () {
|
||||
try {
|
||||
var selection = window.getSelection();
|
||||
if (selectedRange) {
|
||||
try {
|
||||
selection.removeAllRanges();
|
||||
} catch (ex) {
|
||||
document.body.createTextRange().select();
|
||||
document.selection.empty();
|
||||
}
|
||||
'use strict';
|
||||
var readFileIntoDataUrl = function (fileInfo) {
|
||||
var loader = $.Deferred(),
|
||||
fReader = new FileReader();
|
||||
fReader.onload = function (e) {
|
||||
loader.resolve(e.target.result);
|
||||
};
|
||||
fReader.onerror = loader.reject;
|
||||
fReader.onprogress = loader.notify;
|
||||
fReader.readAsDataURL(fileInfo);
|
||||
return loader.promise();
|
||||
};
|
||||
$.fn.cleanHtml = function () {
|
||||
var html = $(this).html();
|
||||
return html && html.replace(/(<br>|\s|<div><br><\/div>| )*$/, '');
|
||||
};
|
||||
$.fn.wysiwyg = function (userOptions) {
|
||||
var editor = this,
|
||||
selectedRange,
|
||||
options,
|
||||
toolbarBtnSelector,
|
||||
updateToolbar = function () {
|
||||
if (options.activeToolbarClass) {
|
||||
$(options.toolbarSelector).find(toolbarBtnSelector).each(function () {
|
||||
try {
|
||||
var command = $(this).data(options.commandRole);
|
||||
if (document.queryCommandState(command)) {
|
||||
$(this).addClass(options.activeToolbarClass);
|
||||
} else {
|
||||
$(this).removeClass(options.activeToolbarClass);
|
||||
}
|
||||
} catch(e){}
|
||||
});
|
||||
}
|
||||
},
|
||||
execCommand = function (commandWithArgs, valueArg) {
|
||||
var commandArr = commandWithArgs.split(' '),
|
||||
command = commandArr.shift(),
|
||||
args = commandArr.join(' ') + (valueArg || '');
|
||||
document.execCommand(command, 0, args);
|
||||
updateToolbar();
|
||||
},
|
||||
bindHotkeys = function (hotKeys) {
|
||||
$.each(hotKeys, function (hotkey, command) {
|
||||
editor.keydown(hotkey, function (e) {
|
||||
if (editor.attr('contenteditable') && editor.is(':visible')) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
execCommand(command);
|
||||
}
|
||||
}).keyup(hotkey, function (e) {
|
||||
if (editor.attr('contenteditable') && editor.is(':visible')) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
getCurrentRange = function () {
|
||||
try {
|
||||
var sel = window.getSelection();
|
||||
if (sel.getRangeAt && sel.rangeCount) {
|
||||
return sel.getRangeAt(0);
|
||||
}
|
||||
} catch(e){}
|
||||
},
|
||||
saveSelection = function () {
|
||||
selectedRange = getCurrentRange();
|
||||
},
|
||||
restoreSelection = function () {
|
||||
try {
|
||||
var selection = window.getSelection();
|
||||
if (selectedRange) {
|
||||
try {
|
||||
selection.removeAllRanges();
|
||||
} catch (ex) {
|
||||
document.body.createTextRange().select();
|
||||
document.selection.empty();
|
||||
}
|
||||
|
||||
selection.addRange(selectedRange);
|
||||
}
|
||||
} catch(e){}
|
||||
},
|
||||
insertFiles = function (files) {
|
||||
editor.focus();
|
||||
$.each(files, function (idx, fileInfo) {
|
||||
if (/^image\//.test(fileInfo.type)) {
|
||||
$.when(readFileIntoDataUrl(fileInfo)).done(function (dataUrl) {
|
||||
execCommand('insertimage', dataUrl);
|
||||
}).fail(function (e) {
|
||||
options.fileUploadError("file-reader", e);
|
||||
});
|
||||
} else {
|
||||
options.fileUploadError("unsupported-file-type", fileInfo.type);
|
||||
}
|
||||
});
|
||||
},
|
||||
markSelection = function (input, color) {
|
||||
restoreSelection();
|
||||
if (document.queryCommandSupported('hiliteColor')) {
|
||||
document.execCommand('hiliteColor', 0, color || 'transparent');
|
||||
}
|
||||
saveSelection();
|
||||
input.data(options.selectionMarker, color);
|
||||
},
|
||||
bindToolbar = function (toolbar, options) {
|
||||
toolbar.find(toolbarBtnSelector).click(function () {
|
||||
restoreSelection();
|
||||
editor.focus();
|
||||
execCommand($(this).data(options.commandRole));
|
||||
saveSelection();
|
||||
});
|
||||
toolbar.find('[data-toggle=dropdown]').click(restoreSelection);
|
||||
selection.addRange(selectedRange);
|
||||
}
|
||||
} catch(e){}
|
||||
},
|
||||
insertFiles = function (files) {
|
||||
editor.focus();
|
||||
$.each(files, function (idx, fileInfo) {
|
||||
if (/^image\//.test(fileInfo.type)) {
|
||||
$.when(readFileIntoDataUrl(fileInfo)).done(function (dataUrl) {
|
||||
execCommand('insertimage', dataUrl);
|
||||
}).fail(function (e) {
|
||||
options.fileUploadError("file-reader", e);
|
||||
});
|
||||
} else {
|
||||
options.fileUploadError("unsupported-file-type", fileInfo.type);
|
||||
}
|
||||
});
|
||||
},
|
||||
markSelection = function (input, color) {
|
||||
restoreSelection();
|
||||
if (document.queryCommandSupported('hiliteColor')) {
|
||||
document.execCommand('hiliteColor', 0, color || 'transparent');
|
||||
}
|
||||
saveSelection();
|
||||
input.data(options.selectionMarker, color);
|
||||
},
|
||||
bindToolbar = function (toolbar, options) {
|
||||
toolbar.find(toolbarBtnSelector).click(function () {
|
||||
restoreSelection();
|
||||
editor.focus();
|
||||
execCommand($(this).data(options.commandRole));
|
||||
saveSelection();
|
||||
});
|
||||
toolbar.find('[data-toggle=dropdown]').click(restoreSelection);
|
||||
|
||||
toolbar.find('input[type=text][data-' + options.commandRole + ']').on('webkitspeechchange change', function () {
|
||||
var newValue = this.value; /* ugly but prevents fake double-calls due to selection restoration */
|
||||
this.value = '';
|
||||
restoreSelection();
|
||||
if (newValue) {
|
||||
editor.focus();
|
||||
execCommand($(this).data(options.commandRole), newValue);
|
||||
}
|
||||
saveSelection();
|
||||
}).on('focus', function () {
|
||||
var input = $(this);
|
||||
if (!input.data(options.selectionMarker)) {
|
||||
markSelection(input, options.selectionColor);
|
||||
input.focus();
|
||||
}
|
||||
}).on('blur', function () {
|
||||
var input = $(this);
|
||||
if (input.data(options.selectionMarker)) {
|
||||
markSelection(input, false);
|
||||
}
|
||||
});
|
||||
toolbar.find('input[type=file][data-' + options.commandRole + ']').change(function () {
|
||||
restoreSelection();
|
||||
if (this.type === 'file' && this.files && this.files.length > 0) {
|
||||
insertFiles(this.files);
|
||||
}
|
||||
saveSelection();
|
||||
this.value = '';
|
||||
});
|
||||
},
|
||||
initFileDrops = function () {
|
||||
editor.on('dragenter dragover', false)
|
||||
.on('drop', function (e) {
|
||||
var dataTransfer = e.originalEvent.dataTransfer;
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
|
||||
insertFiles(dataTransfer.files);
|
||||
}
|
||||
});
|
||||
};
|
||||
options = $.extend({}, $.fn.wysiwyg.defaults, userOptions);
|
||||
toolbarBtnSelector = 'a[data-' + options.commandRole + '],button[data-' + options.commandRole + '],input[type=button][data-' + options.commandRole + ']';
|
||||
bindHotkeys(options.hotKeys);
|
||||
if (options.dragAndDropImages) {
|
||||
initFileDrops();
|
||||
}
|
||||
bindToolbar($(options.toolbarSelector), options);
|
||||
editor.attr('contenteditable', true)
|
||||
.on('mouseup keyup mouseout', function () {
|
||||
saveSelection();
|
||||
updateToolbar();
|
||||
});
|
||||
$(window).bind('touchend', function (e) {
|
||||
var isInside = (editor.is(e.target) || editor.has(e.target).length > 0),
|
||||
currentRange = getCurrentRange(),
|
||||
clear = currentRange && (currentRange.startContainer === currentRange.endContainer && currentRange.startOffset === currentRange.endOffset);
|
||||
if (!clear || isInside) {
|
||||
saveSelection();
|
||||
updateToolbar();
|
||||
}
|
||||
});
|
||||
return this;
|
||||
};
|
||||
$.fn.wysiwyg.defaults = {
|
||||
hotKeys: {
|
||||
'ctrl+b meta+b': 'bold',
|
||||
'ctrl+i meta+i': 'italic',
|
||||
'ctrl+u meta+u': 'underline',
|
||||
'ctrl+z meta+z': 'undo',
|
||||
'ctrl+y meta+y meta+shift+z': 'redo',
|
||||
'ctrl+l meta+l': 'justifyleft',
|
||||
'ctrl+r meta+r': 'justifyright',
|
||||
'ctrl+e meta+e': 'justifycenter',
|
||||
'ctrl+j meta+j': 'justifyfull',
|
||||
'shift+tab': 'outdent',
|
||||
'tab': 'indent'
|
||||
},
|
||||
toolbarSelector: '[data-role=editor-toolbar]',
|
||||
commandRole: 'edit',
|
||||
activeToolbarClass: 'btn-info',
|
||||
selectionMarker: 'edit-focus-marker',
|
||||
selectionColor: 'darkgrey',
|
||||
dragAndDropImages: true,
|
||||
fileUploadError: function (reason, detail) { console.log("File upload error", reason, detail); }
|
||||
};
|
||||
toolbar.find('input[type=text][data-' + options.commandRole + ']').on('webkitspeechchange change', function () {
|
||||
var newValue = this.value; /* ugly but prevents fake double-calls due to selection restoration */
|
||||
this.value = '';
|
||||
restoreSelection();
|
||||
if (newValue) {
|
||||
editor.focus();
|
||||
execCommand($(this).data(options.commandRole), newValue);
|
||||
}
|
||||
saveSelection();
|
||||
}).on('focus', function () {
|
||||
var input = $(this);
|
||||
if (!input.data(options.selectionMarker)) {
|
||||
markSelection(input, options.selectionColor);
|
||||
input.focus();
|
||||
}
|
||||
}).on('blur', function () {
|
||||
var input = $(this);
|
||||
if (input.data(options.selectionMarker)) {
|
||||
markSelection(input, false);
|
||||
}
|
||||
});
|
||||
toolbar.find('input[type=file][data-' + options.commandRole + ']').change(function () {
|
||||
restoreSelection();
|
||||
if (this.type === 'file' && this.files && this.files.length > 0) {
|
||||
insertFiles(this.files);
|
||||
}
|
||||
saveSelection();
|
||||
this.value = '';
|
||||
});
|
||||
},
|
||||
initFileDrops = function () {
|
||||
editor.on('dragenter dragover', false)
|
||||
.on('drop', function (e) {
|
||||
var dataTransfer = e.originalEvent.dataTransfer;
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
|
||||
insertFiles(dataTransfer.files);
|
||||
}
|
||||
});
|
||||
};
|
||||
options = $.extend({}, $.fn.wysiwyg.defaults, userOptions);
|
||||
toolbarBtnSelector = 'a[data-' + options.commandRole + '],button[data-' + options.commandRole + '],input[type=button][data-' + options.commandRole + ']';
|
||||
bindHotkeys(options.hotKeys);
|
||||
if (options.dragAndDropImages) {
|
||||
initFileDrops();
|
||||
}
|
||||
bindToolbar($(options.toolbarSelector), options);
|
||||
editor.attr('contenteditable', true)
|
||||
.on('mouseup keyup mouseout', function () {
|
||||
saveSelection();
|
||||
updateToolbar();
|
||||
});
|
||||
$(window).bind('touchend', function (e) {
|
||||
var isInside = (editor.is(e.target) || editor.has(e.target).length > 0),
|
||||
currentRange = getCurrentRange(),
|
||||
clear = currentRange && (currentRange.startContainer === currentRange.endContainer && currentRange.startOffset === currentRange.endOffset);
|
||||
if (!clear || isInside) {
|
||||
saveSelection();
|
||||
updateToolbar();
|
||||
}
|
||||
});
|
||||
return this;
|
||||
};
|
||||
$.fn.wysiwyg.defaults = {
|
||||
hotKeys: {
|
||||
'ctrl+b meta+b': 'bold',
|
||||
'ctrl+i meta+i': 'italic',
|
||||
'ctrl+u meta+u': 'underline',
|
||||
'ctrl+z meta+z': 'undo',
|
||||
'ctrl+y meta+y meta+shift+z': 'redo',
|
||||
'ctrl+l meta+l': 'justifyleft',
|
||||
'ctrl+r meta+r': 'justifyright',
|
||||
'ctrl+e meta+e': 'justifycenter',
|
||||
'ctrl+j meta+j': 'justifyfull',
|
||||
'shift+tab': 'outdent',
|
||||
'tab': 'indent'
|
||||
},
|
||||
toolbarSelector: '[data-role=editor-toolbar]',
|
||||
commandRole: 'edit',
|
||||
activeToolbarClass: 'btn-info',
|
||||
selectionMarker: 'edit-focus-marker',
|
||||
selectionColor: 'darkgrey',
|
||||
dragAndDropImages: true,
|
||||
fileUploadError: function (reason, detail) { console.log("File upload error", reason, detail); }
|
||||
};
|
||||
}(window.jQuery));
|
||||
|
||||
@@ -16,98 +16,98 @@
|
||||
*/
|
||||
|
||||
(function(jQuery){
|
||||
|
||||
jQuery.hotkeys = {
|
||||
version: "0.8",
|
||||
|
||||
jQuery.hotkeys = {
|
||||
version: "0.8",
|
||||
|
||||
specialKeys: {
|
||||
8: "backspace", 9: "tab", 10: "return", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
|
||||
20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home",
|
||||
37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del",
|
||||
96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
|
||||
104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/",
|
||||
112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8",
|
||||
120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 186: ";", 191: "/",
|
||||
220: "\\", 222: "'", 224: "meta"
|
||||
},
|
||||
|
||||
shiftNums: {
|
||||
"`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&",
|
||||
"8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<",
|
||||
".": ">", "/": "?", "\\": "|"
|
||||
}
|
||||
};
|
||||
specialKeys: {
|
||||
8: "backspace", 9: "tab", 10: "return", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
|
||||
20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home",
|
||||
37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del",
|
||||
96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
|
||||
104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/",
|
||||
112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8",
|
||||
120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 186: ";", 191: "/",
|
||||
220: "\\", 222: "'", 224: "meta"
|
||||
},
|
||||
|
||||
shiftNums: {
|
||||
"`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&",
|
||||
"8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<",
|
||||
".": ">", "/": "?", "\\": "|"
|
||||
}
|
||||
};
|
||||
|
||||
function keyHandler( handleObj ) {
|
||||
if (typeof handleObj.data == 'undefined') return;
|
||||
function keyHandler( handleObj ) {
|
||||
if (typeof handleObj.data == 'undefined') return;
|
||||
|
||||
if ( typeof handleObj.data === "string" ) {
|
||||
handleObj.data = { keys: handleObj.data };
|
||||
}
|
||||
if ( typeof handleObj.data === "string" ) {
|
||||
handleObj.data = { keys: handleObj.data };
|
||||
}
|
||||
|
||||
// Only care when a possible input has been specified
|
||||
if ( !handleObj.data || !handleObj.data.keys || typeof handleObj.data.keys !== "string" ) {
|
||||
return;
|
||||
}
|
||||
// Only care when a possible input has been specified
|
||||
if ( !handleObj.data || !handleObj.data.keys || typeof handleObj.data.keys !== "string" ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var origHandler = handleObj.handler,
|
||||
keys = handleObj.data.keys.toLowerCase().split(" "),
|
||||
textAcceptingInputTypes = ["text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime", "datetime-local", "search", "color", "tel"];
|
||||
|
||||
handleObj.handler = function( event ) {
|
||||
// Don't fire in text-accepting inputs that we didn't directly bind to
|
||||
if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) ||
|
||||
jQuery.inArray(event.target.type, textAcceptingInputTypes) > -1 ) ) {
|
||||
return;
|
||||
}
|
||||
var origHandler = handleObj.handler,
|
||||
keys = handleObj.data.keys.toLowerCase().split(" "),
|
||||
textAcceptingInputTypes = ["text", "password", "number", "email", "url", "range", "date", "month", "week", "time", "datetime", "datetime-local", "search", "color", "tel"];
|
||||
|
||||
handleObj.handler = function( event ) {
|
||||
// Don't fire in text-accepting inputs that we didn't directly bind to
|
||||
if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) ||
|
||||
jQuery.inArray(event.target.type, textAcceptingInputTypes) > -1 ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var special = jQuery.hotkeys.specialKeys[ event.keyCode ],
|
||||
// character codes are available only in keypress
|
||||
character = (event.type === "keydown" || event.type === "keypress") && String.fromCharCode( event.which ).toLowerCase()
|
||||
modif = "", possible = {};
|
||||
var special = jQuery.hotkeys.specialKeys[ event.keyCode ],
|
||||
// character codes are available only in keypress
|
||||
character = (event.type === "keydown" || event.type === "keypress") && String.fromCharCode( event.which ).toLowerCase()
|
||||
modif = "", possible = {};
|
||||
|
||||
// check combinations (alt|ctrl|shift+anything)
|
||||
if ( event.altKey && special !== "alt" ) {
|
||||
modif += "alt+";
|
||||
}
|
||||
// check combinations (alt|ctrl|shift+anything)
|
||||
if ( event.altKey && special !== "alt" ) {
|
||||
modif += "alt+";
|
||||
}
|
||||
|
||||
if ( event.ctrlKey && special !== "ctrl" ) {
|
||||
modif += "ctrl+";
|
||||
}
|
||||
|
||||
// TODO: Need to make sure this works consistently across platforms
|
||||
if ( event.metaKey && !event.ctrlKey && special !== "meta" ) {
|
||||
modif += "meta+";
|
||||
}
|
||||
if ( event.ctrlKey && special !== "ctrl" ) {
|
||||
modif += "ctrl+";
|
||||
}
|
||||
|
||||
// TODO: Need to make sure this works consistently across platforms
|
||||
if ( event.metaKey && !event.ctrlKey && special !== "meta" ) {
|
||||
modif += "meta+";
|
||||
}
|
||||
|
||||
if ( event.shiftKey && special !== "shift" ) {
|
||||
modif += "shift+";
|
||||
}
|
||||
if ( event.shiftKey && special !== "shift" ) {
|
||||
modif += "shift+";
|
||||
}
|
||||
|
||||
if ( special ) {
|
||||
possible[ modif + special ] = true;
|
||||
}
|
||||
if ( special ) {
|
||||
possible[ modif + special ] = true;
|
||||
}
|
||||
|
||||
if ( character ) {
|
||||
possible[ modif + character ] = true;
|
||||
possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true;
|
||||
if ( character ) {
|
||||
possible[ modif + character ] = true;
|
||||
possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true;
|
||||
|
||||
// "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
|
||||
if ( modif === "shift+" ) {
|
||||
possible[ jQuery.hotkeys.shiftNums[ character ] ] = true;
|
||||
}
|
||||
}
|
||||
// "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
|
||||
if ( modif === "shift+" ) {
|
||||
possible[ jQuery.hotkeys.shiftNums[ character ] ] = true;
|
||||
}
|
||||
}
|
||||
|
||||
for ( var i = 0, l = keys.length; i < l; i++ ) {
|
||||
if ( possible[ keys[i] ] ) {
|
||||
return origHandler.apply( this, arguments );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
for ( var i = 0, l = keys.length; i < l; i++ ) {
|
||||
if ( possible[ keys[i] ] ) {
|
||||
return origHandler.apply( this, arguments );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
jQuery.each([ "keydown", "keyup", "keypress" ], function() {
|
||||
jQuery.event.special[ this ] = { add: keyHandler };
|
||||
});
|
||||
jQuery.each([ "keydown", "keyup", "keypress" ], function() {
|
||||
jQuery.event.special[ this ] = { add: keyHandler };
|
||||
});
|
||||
|
||||
})( this.jQuery );
|
||||
|
||||
14480
static/js/lib/jquery.js
vendored
14480
static/js/lib/jquery.js
vendored
File diff suppressed because it is too large
Load Diff
878
static/js/lib/jquery.ui.widget.js
vendored
878
static/js/lib/jquery.ui.widget.js
vendored
@@ -20,511 +20,511 @@
|
||||
}(function( $, undefined ) {
|
||||
|
||||
var uuid = 0,
|
||||
slice = Array.prototype.slice,
|
||||
_cleanData = $.cleanData;
|
||||
slice = Array.prototype.slice,
|
||||
_cleanData = $.cleanData;
|
||||
$.cleanData = function( elems ) {
|
||||
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
|
||||
try {
|
||||
$( elem ).triggerHandler( "remove" );
|
||||
// http://bugs.jquery.com/ticket/8235
|
||||
} catch( e ) {}
|
||||
}
|
||||
_cleanData( elems );
|
||||
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
|
||||
try {
|
||||
$( elem ).triggerHandler( "remove" );
|
||||
// http://bugs.jquery.com/ticket/8235
|
||||
} catch( e ) {}
|
||||
}
|
||||
_cleanData( elems );
|
||||
};
|
||||
|
||||
$.widget = function( name, base, prototype ) {
|
||||
var fullName, existingConstructor, constructor, basePrototype,
|
||||
// proxiedPrototype allows the provided prototype to remain unmodified
|
||||
// so that it can be used as a mixin for multiple widgets (#8876)
|
||||
proxiedPrototype = {},
|
||||
namespace = name.split( "." )[ 0 ];
|
||||
var fullName, existingConstructor, constructor, basePrototype,
|
||||
// proxiedPrototype allows the provided prototype to remain unmodified
|
||||
// so that it can be used as a mixin for multiple widgets (#8876)
|
||||
proxiedPrototype = {},
|
||||
namespace = name.split( "." )[ 0 ];
|
||||
|
||||
name = name.split( "." )[ 1 ];
|
||||
fullName = namespace + "-" + name;
|
||||
name = name.split( "." )[ 1 ];
|
||||
fullName = namespace + "-" + name;
|
||||
|
||||
if ( !prototype ) {
|
||||
prototype = base;
|
||||
base = $.Widget;
|
||||
}
|
||||
if ( !prototype ) {
|
||||
prototype = base;
|
||||
base = $.Widget;
|
||||
}
|
||||
|
||||
// create selector for plugin
|
||||
$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
|
||||
return !!$.data( elem, fullName );
|
||||
};
|
||||
// create selector for plugin
|
||||
$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
|
||||
return !!$.data( elem, fullName );
|
||||
};
|
||||
|
||||
$[ namespace ] = $[ namespace ] || {};
|
||||
existingConstructor = $[ namespace ][ name ];
|
||||
constructor = $[ namespace ][ name ] = function( options, element ) {
|
||||
// allow instantiation without "new" keyword
|
||||
if ( !this._createWidget ) {
|
||||
return new constructor( options, element );
|
||||
}
|
||||
$[ namespace ] = $[ namespace ] || {};
|
||||
existingConstructor = $[ namespace ][ name ];
|
||||
constructor = $[ namespace ][ name ] = function( options, element ) {
|
||||
// allow instantiation without "new" keyword
|
||||
if ( !this._createWidget ) {
|
||||
return new constructor( options, element );
|
||||
}
|
||||
|
||||
// allow instantiation without initializing for simple inheritance
|
||||
// must use "new" keyword (the code above always passes args)
|
||||
if ( arguments.length ) {
|
||||
this._createWidget( options, element );
|
||||
}
|
||||
};
|
||||
// extend with the existing constructor to carry over any static properties
|
||||
$.extend( constructor, existingConstructor, {
|
||||
version: prototype.version,
|
||||
// copy the object used to create the prototype in case we need to
|
||||
// redefine the widget later
|
||||
_proto: $.extend( {}, prototype ),
|
||||
// track widgets that inherit from this widget in case this widget is
|
||||
// redefined after a widget inherits from it
|
||||
_childConstructors: []
|
||||
});
|
||||
// allow instantiation without initializing for simple inheritance
|
||||
// must use "new" keyword (the code above always passes args)
|
||||
if ( arguments.length ) {
|
||||
this._createWidget( options, element );
|
||||
}
|
||||
};
|
||||
// extend with the existing constructor to carry over any static properties
|
||||
$.extend( constructor, existingConstructor, {
|
||||
version: prototype.version,
|
||||
// copy the object used to create the prototype in case we need to
|
||||
// redefine the widget later
|
||||
_proto: $.extend( {}, prototype ),
|
||||
// track widgets that inherit from this widget in case this widget is
|
||||
// redefined after a widget inherits from it
|
||||
_childConstructors: []
|
||||
});
|
||||
|
||||
basePrototype = new base();
|
||||
// we need to make the options hash a property directly on the new instance
|
||||
// otherwise we'll modify the options hash on the prototype that we're
|
||||
// inheriting from
|
||||
basePrototype.options = $.widget.extend( {}, basePrototype.options );
|
||||
$.each( prototype, function( prop, value ) {
|
||||
if ( !$.isFunction( value ) ) {
|
||||
proxiedPrototype[ prop ] = value;
|
||||
return;
|
||||
}
|
||||
proxiedPrototype[ prop ] = (function() {
|
||||
var _super = function() {
|
||||
return base.prototype[ prop ].apply( this, arguments );
|
||||
},
|
||||
_superApply = function( args ) {
|
||||
return base.prototype[ prop ].apply( this, args );
|
||||
};
|
||||
return function() {
|
||||
var __super = this._super,
|
||||
__superApply = this._superApply,
|
||||
returnValue;
|
||||
basePrototype = new base();
|
||||
// we need to make the options hash a property directly on the new instance
|
||||
// otherwise we'll modify the options hash on the prototype that we're
|
||||
// inheriting from
|
||||
basePrototype.options = $.widget.extend( {}, basePrototype.options );
|
||||
$.each( prototype, function( prop, value ) {
|
||||
if ( !$.isFunction( value ) ) {
|
||||
proxiedPrototype[ prop ] = value;
|
||||
return;
|
||||
}
|
||||
proxiedPrototype[ prop ] = (function() {
|
||||
var _super = function() {
|
||||
return base.prototype[ prop ].apply( this, arguments );
|
||||
},
|
||||
_superApply = function( args ) {
|
||||
return base.prototype[ prop ].apply( this, args );
|
||||
};
|
||||
return function() {
|
||||
var __super = this._super,
|
||||
__superApply = this._superApply,
|
||||
returnValue;
|
||||
|
||||
this._super = _super;
|
||||
this._superApply = _superApply;
|
||||
this._super = _super;
|
||||
this._superApply = _superApply;
|
||||
|
||||
returnValue = value.apply( this, arguments );
|
||||
returnValue = value.apply( this, arguments );
|
||||
|
||||
this._super = __super;
|
||||
this._superApply = __superApply;
|
||||
this._super = __super;
|
||||
this._superApply = __superApply;
|
||||
|
||||
return returnValue;
|
||||
};
|
||||
})();
|
||||
});
|
||||
constructor.prototype = $.widget.extend( basePrototype, {
|
||||
// TODO: remove support for widgetEventPrefix
|
||||
// always use the name + a colon as the prefix, e.g., draggable:start
|
||||
// don't prefix for widgets that aren't DOM-based
|
||||
widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
|
||||
}, proxiedPrototype, {
|
||||
constructor: constructor,
|
||||
namespace: namespace,
|
||||
widgetName: name,
|
||||
widgetFullName: fullName
|
||||
});
|
||||
return returnValue;
|
||||
};
|
||||
})();
|
||||
});
|
||||
constructor.prototype = $.widget.extend( basePrototype, {
|
||||
// TODO: remove support for widgetEventPrefix
|
||||
// always use the name + a colon as the prefix, e.g., draggable:start
|
||||
// don't prefix for widgets that aren't DOM-based
|
||||
widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
|
||||
}, proxiedPrototype, {
|
||||
constructor: constructor,
|
||||
namespace: namespace,
|
||||
widgetName: name,
|
||||
widgetFullName: fullName
|
||||
});
|
||||
|
||||
// If this widget is being redefined then we need to find all widgets that
|
||||
// are inheriting from it and redefine all of them so that they inherit from
|
||||
// the new version of this widget. We're essentially trying to replace one
|
||||
// level in the prototype chain.
|
||||
if ( existingConstructor ) {
|
||||
$.each( existingConstructor._childConstructors, function( i, child ) {
|
||||
var childPrototype = child.prototype;
|
||||
// If this widget is being redefined then we need to find all widgets that
|
||||
// are inheriting from it and redefine all of them so that they inherit from
|
||||
// the new version of this widget. We're essentially trying to replace one
|
||||
// level in the prototype chain.
|
||||
if ( existingConstructor ) {
|
||||
$.each( existingConstructor._childConstructors, function( i, child ) {
|
||||
var childPrototype = child.prototype;
|
||||
|
||||
// redefine the child widget using the same prototype that was
|
||||
// originally used, but inherit from the new version of the base
|
||||
$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
|
||||
});
|
||||
// remove the list of existing child constructors from the old constructor
|
||||
// so the old child constructors can be garbage collected
|
||||
delete existingConstructor._childConstructors;
|
||||
} else {
|
||||
base._childConstructors.push( constructor );
|
||||
}
|
||||
// redefine the child widget using the same prototype that was
|
||||
// originally used, but inherit from the new version of the base
|
||||
$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
|
||||
});
|
||||
// remove the list of existing child constructors from the old constructor
|
||||
// so the old child constructors can be garbage collected
|
||||
delete existingConstructor._childConstructors;
|
||||
} else {
|
||||
base._childConstructors.push( constructor );
|
||||
}
|
||||
|
||||
$.widget.bridge( name, constructor );
|
||||
$.widget.bridge( name, constructor );
|
||||
};
|
||||
|
||||
$.widget.extend = function( target ) {
|
||||
var input = slice.call( arguments, 1 ),
|
||||
inputIndex = 0,
|
||||
inputLength = input.length,
|
||||
key,
|
||||
value;
|
||||
for ( ; inputIndex < inputLength; inputIndex++ ) {
|
||||
for ( key in input[ inputIndex ] ) {
|
||||
value = input[ inputIndex ][ key ];
|
||||
if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
|
||||
// Clone objects
|
||||
if ( $.isPlainObject( value ) ) {
|
||||
target[ key ] = $.isPlainObject( target[ key ] ) ?
|
||||
$.widget.extend( {}, target[ key ], value ) :
|
||||
// Don't extend strings, arrays, etc. with objects
|
||||
$.widget.extend( {}, value );
|
||||
// Copy everything else by reference
|
||||
} else {
|
||||
target[ key ] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
var input = slice.call( arguments, 1 ),
|
||||
inputIndex = 0,
|
||||
inputLength = input.length,
|
||||
key,
|
||||
value;
|
||||
for ( ; inputIndex < inputLength; inputIndex++ ) {
|
||||
for ( key in input[ inputIndex ] ) {
|
||||
value = input[ inputIndex ][ key ];
|
||||
if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
|
||||
// Clone objects
|
||||
if ( $.isPlainObject( value ) ) {
|
||||
target[ key ] = $.isPlainObject( target[ key ] ) ?
|
||||
$.widget.extend( {}, target[ key ], value ) :
|
||||
// Don't extend strings, arrays, etc. with objects
|
||||
$.widget.extend( {}, value );
|
||||
// Copy everything else by reference
|
||||
} else {
|
||||
target[ key ] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
};
|
||||
|
||||
$.widget.bridge = function( name, object ) {
|
||||
var fullName = object.prototype.widgetFullName || name;
|
||||
$.fn[ name ] = function( options ) {
|
||||
var isMethodCall = typeof options === "string",
|
||||
args = slice.call( arguments, 1 ),
|
||||
returnValue = this;
|
||||
var fullName = object.prototype.widgetFullName || name;
|
||||
$.fn[ name ] = function( options ) {
|
||||
var isMethodCall = typeof options === "string",
|
||||
args = slice.call( arguments, 1 ),
|
||||
returnValue = this;
|
||||
|
||||
// allow multiple hashes to be passed on init
|
||||
options = !isMethodCall && args.length ?
|
||||
$.widget.extend.apply( null, [ options ].concat(args) ) :
|
||||
options;
|
||||
// allow multiple hashes to be passed on init
|
||||
options = !isMethodCall && args.length ?
|
||||
$.widget.extend.apply( null, [ options ].concat(args) ) :
|
||||
options;
|
||||
|
||||
if ( isMethodCall ) {
|
||||
this.each(function() {
|
||||
var methodValue,
|
||||
instance = $.data( this, fullName );
|
||||
if ( !instance ) {
|
||||
return $.error( "cannot call methods on " + name + " prior to initialization; " +
|
||||
"attempted to call method '" + options + "'" );
|
||||
}
|
||||
if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
|
||||
return $.error( "no such method '" + options + "' for " + name + " widget instance" );
|
||||
}
|
||||
methodValue = instance[ options ].apply( instance, args );
|
||||
if ( methodValue !== instance && methodValue !== undefined ) {
|
||||
returnValue = methodValue && methodValue.jquery ?
|
||||
returnValue.pushStack( methodValue.get() ) :
|
||||
methodValue;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.each(function() {
|
||||
var instance = $.data( this, fullName );
|
||||
if ( instance ) {
|
||||
instance.option( options || {} )._init();
|
||||
} else {
|
||||
$.data( this, fullName, new object( options, this ) );
|
||||
}
|
||||
});
|
||||
}
|
||||
if ( isMethodCall ) {
|
||||
this.each(function() {
|
||||
var methodValue,
|
||||
instance = $.data( this, fullName );
|
||||
if ( !instance ) {
|
||||
return $.error( "cannot call methods on " + name + " prior to initialization; " +
|
||||
"attempted to call method '" + options + "'" );
|
||||
}
|
||||
if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
|
||||
return $.error( "no such method '" + options + "' for " + name + " widget instance" );
|
||||
}
|
||||
methodValue = instance[ options ].apply( instance, args );
|
||||
if ( methodValue !== instance && methodValue !== undefined ) {
|
||||
returnValue = methodValue && methodValue.jquery ?
|
||||
returnValue.pushStack( methodValue.get() ) :
|
||||
methodValue;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.each(function() {
|
||||
var instance = $.data( this, fullName );
|
||||
if ( instance ) {
|
||||
instance.option( options || {} )._init();
|
||||
} else {
|
||||
$.data( this, fullName, new object( options, this ) );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
};
|
||||
return returnValue;
|
||||
};
|
||||
};
|
||||
|
||||
$.Widget = function( /* options, element */ ) {};
|
||||
$.Widget._childConstructors = [];
|
||||
|
||||
$.Widget.prototype = {
|
||||
widgetName: "widget",
|
||||
widgetEventPrefix: "",
|
||||
defaultElement: "<div>",
|
||||
options: {
|
||||
disabled: false,
|
||||
widgetName: "widget",
|
||||
widgetEventPrefix: "",
|
||||
defaultElement: "<div>",
|
||||
options: {
|
||||
disabled: false,
|
||||
|
||||
// callbacks
|
||||
create: null
|
||||
},
|
||||
_createWidget: function( options, element ) {
|
||||
element = $( element || this.defaultElement || this )[ 0 ];
|
||||
this.element = $( element );
|
||||
this.uuid = uuid++;
|
||||
this.eventNamespace = "." + this.widgetName + this.uuid;
|
||||
this.options = $.widget.extend( {},
|
||||
this.options,
|
||||
this._getCreateOptions(),
|
||||
options );
|
||||
// callbacks
|
||||
create: null
|
||||
},
|
||||
_createWidget: function( options, element ) {
|
||||
element = $( element || this.defaultElement || this )[ 0 ];
|
||||
this.element = $( element );
|
||||
this.uuid = uuid++;
|
||||
this.eventNamespace = "." + this.widgetName + this.uuid;
|
||||
this.options = $.widget.extend( {},
|
||||
this.options,
|
||||
this._getCreateOptions(),
|
||||
options );
|
||||
|
||||
this.bindings = $();
|
||||
this.hoverable = $();
|
||||
this.focusable = $();
|
||||
this.bindings = $();
|
||||
this.hoverable = $();
|
||||
this.focusable = $();
|
||||
|
||||
if ( element !== this ) {
|
||||
$.data( element, this.widgetFullName, this );
|
||||
this._on( true, this.element, {
|
||||
remove: function( event ) {
|
||||
if ( event.target === element ) {
|
||||
this.destroy();
|
||||
}
|
||||
}
|
||||
});
|
||||
this.document = $( element.style ?
|
||||
// element within the document
|
||||
element.ownerDocument :
|
||||
// element is window or document
|
||||
element.document || element );
|
||||
this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
|
||||
}
|
||||
if ( element !== this ) {
|
||||
$.data( element, this.widgetFullName, this );
|
||||
this._on( true, this.element, {
|
||||
remove: function( event ) {
|
||||
if ( event.target === element ) {
|
||||
this.destroy();
|
||||
}
|
||||
}
|
||||
});
|
||||
this.document = $( element.style ?
|
||||
// element within the document
|
||||
element.ownerDocument :
|
||||
// element is window or document
|
||||
element.document || element );
|
||||
this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
|
||||
}
|
||||
|
||||
this._create();
|
||||
this._trigger( "create", null, this._getCreateEventData() );
|
||||
this._init();
|
||||
},
|
||||
_getCreateOptions: $.noop,
|
||||
_getCreateEventData: $.noop,
|
||||
_create: $.noop,
|
||||
_init: $.noop,
|
||||
this._create();
|
||||
this._trigger( "create", null, this._getCreateEventData() );
|
||||
this._init();
|
||||
},
|
||||
_getCreateOptions: $.noop,
|
||||
_getCreateEventData: $.noop,
|
||||
_create: $.noop,
|
||||
_init: $.noop,
|
||||
|
||||
destroy: function() {
|
||||
this._destroy();
|
||||
// we can probably remove the unbind calls in 2.0
|
||||
// all event bindings should go through this._on()
|
||||
this.element
|
||||
.unbind( this.eventNamespace )
|
||||
// 1.9 BC for #7810
|
||||
// TODO remove dual storage
|
||||
.removeData( this.widgetName )
|
||||
.removeData( this.widgetFullName )
|
||||
// support: jquery <1.6.3
|
||||
// http://bugs.jquery.com/ticket/9413
|
||||
.removeData( $.camelCase( this.widgetFullName ) );
|
||||
this.widget()
|
||||
.unbind( this.eventNamespace )
|
||||
.removeAttr( "aria-disabled" )
|
||||
.removeClass(
|
||||
this.widgetFullName + "-disabled " +
|
||||
"ui-state-disabled" );
|
||||
destroy: function() {
|
||||
this._destroy();
|
||||
// we can probably remove the unbind calls in 2.0
|
||||
// all event bindings should go through this._on()
|
||||
this.element
|
||||
.unbind( this.eventNamespace )
|
||||
// 1.9 BC for #7810
|
||||
// TODO remove dual storage
|
||||
.removeData( this.widgetName )
|
||||
.removeData( this.widgetFullName )
|
||||
// support: jquery <1.6.3
|
||||
// http://bugs.jquery.com/ticket/9413
|
||||
.removeData( $.camelCase( this.widgetFullName ) );
|
||||
this.widget()
|
||||
.unbind( this.eventNamespace )
|
||||
.removeAttr( "aria-disabled" )
|
||||
.removeClass(
|
||||
this.widgetFullName + "-disabled " +
|
||||
"ui-state-disabled" );
|
||||
|
||||
// clean up events and states
|
||||
this.bindings.unbind( this.eventNamespace );
|
||||
this.hoverable.removeClass( "ui-state-hover" );
|
||||
this.focusable.removeClass( "ui-state-focus" );
|
||||
},
|
||||
_destroy: $.noop,
|
||||
// clean up events and states
|
||||
this.bindings.unbind( this.eventNamespace );
|
||||
this.hoverable.removeClass( "ui-state-hover" );
|
||||
this.focusable.removeClass( "ui-state-focus" );
|
||||
},
|
||||
_destroy: $.noop,
|
||||
|
||||
widget: function() {
|
||||
return this.element;
|
||||
},
|
||||
widget: function() {
|
||||
return this.element;
|
||||
},
|
||||
|
||||
option: function( key, value ) {
|
||||
var options = key,
|
||||
parts,
|
||||
curOption,
|
||||
i;
|
||||
option: function( key, value ) {
|
||||
var options = key,
|
||||
parts,
|
||||
curOption,
|
||||
i;
|
||||
|
||||
if ( arguments.length === 0 ) {
|
||||
// don't return a reference to the internal hash
|
||||
return $.widget.extend( {}, this.options );
|
||||
}
|
||||
if ( arguments.length === 0 ) {
|
||||
// don't return a reference to the internal hash
|
||||
return $.widget.extend( {}, this.options );
|
||||
}
|
||||
|
||||
if ( typeof key === "string" ) {
|
||||
// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
|
||||
options = {};
|
||||
parts = key.split( "." );
|
||||
key = parts.shift();
|
||||
if ( parts.length ) {
|
||||
curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
|
||||
for ( i = 0; i < parts.length - 1; i++ ) {
|
||||
curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
|
||||
curOption = curOption[ parts[ i ] ];
|
||||
}
|
||||
key = parts.pop();
|
||||
if ( value === undefined ) {
|
||||
return curOption[ key ] === undefined ? null : curOption[ key ];
|
||||
}
|
||||
curOption[ key ] = value;
|
||||
} else {
|
||||
if ( value === undefined ) {
|
||||
return this.options[ key ] === undefined ? null : this.options[ key ];
|
||||
}
|
||||
options[ key ] = value;
|
||||
}
|
||||
}
|
||||
if ( typeof key === "string" ) {
|
||||
// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
|
||||
options = {};
|
||||
parts = key.split( "." );
|
||||
key = parts.shift();
|
||||
if ( parts.length ) {
|
||||
curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
|
||||
for ( i = 0; i < parts.length - 1; i++ ) {
|
||||
curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
|
||||
curOption = curOption[ parts[ i ] ];
|
||||
}
|
||||
key = parts.pop();
|
||||
if ( value === undefined ) {
|
||||
return curOption[ key ] === undefined ? null : curOption[ key ];
|
||||
}
|
||||
curOption[ key ] = value;
|
||||
} else {
|
||||
if ( value === undefined ) {
|
||||
return this.options[ key ] === undefined ? null : this.options[ key ];
|
||||
}
|
||||
options[ key ] = value;
|
||||
}
|
||||
}
|
||||
|
||||
this._setOptions( options );
|
||||
this._setOptions( options );
|
||||
|
||||
return this;
|
||||
},
|
||||
_setOptions: function( options ) {
|
||||
var key;
|
||||
return this;
|
||||
},
|
||||
_setOptions: function( options ) {
|
||||
var key;
|
||||
|
||||
for ( key in options ) {
|
||||
this._setOption( key, options[ key ] );
|
||||
}
|
||||
for ( key in options ) {
|
||||
this._setOption( key, options[ key ] );
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
_setOption: function( key, value ) {
|
||||
this.options[ key ] = value;
|
||||
return this;
|
||||
},
|
||||
_setOption: function( key, value ) {
|
||||
this.options[ key ] = value;
|
||||
|
||||
if ( key === "disabled" ) {
|
||||
this.widget()
|
||||
.toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
|
||||
.attr( "aria-disabled", value );
|
||||
this.hoverable.removeClass( "ui-state-hover" );
|
||||
this.focusable.removeClass( "ui-state-focus" );
|
||||
}
|
||||
if ( key === "disabled" ) {
|
||||
this.widget()
|
||||
.toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
|
||||
.attr( "aria-disabled", value );
|
||||
this.hoverable.removeClass( "ui-state-hover" );
|
||||
this.focusable.removeClass( "ui-state-focus" );
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
return this;
|
||||
},
|
||||
|
||||
enable: function() {
|
||||
return this._setOption( "disabled", false );
|
||||
},
|
||||
disable: function() {
|
||||
return this._setOption( "disabled", true );
|
||||
},
|
||||
enable: function() {
|
||||
return this._setOption( "disabled", false );
|
||||
},
|
||||
disable: function() {
|
||||
return this._setOption( "disabled", true );
|
||||
},
|
||||
|
||||
_on: function( suppressDisabledCheck, element, handlers ) {
|
||||
var delegateElement,
|
||||
instance = this;
|
||||
_on: function( suppressDisabledCheck, element, handlers ) {
|
||||
var delegateElement,
|
||||
instance = this;
|
||||
|
||||
// no suppressDisabledCheck flag, shuffle arguments
|
||||
if ( typeof suppressDisabledCheck !== "boolean" ) {
|
||||
handlers = element;
|
||||
element = suppressDisabledCheck;
|
||||
suppressDisabledCheck = false;
|
||||
}
|
||||
// no suppressDisabledCheck flag, shuffle arguments
|
||||
if ( typeof suppressDisabledCheck !== "boolean" ) {
|
||||
handlers = element;
|
||||
element = suppressDisabledCheck;
|
||||
suppressDisabledCheck = false;
|
||||
}
|
||||
|
||||
// no element argument, shuffle and use this.element
|
||||
if ( !handlers ) {
|
||||
handlers = element;
|
||||
element = this.element;
|
||||
delegateElement = this.widget();
|
||||
} else {
|
||||
// accept selectors, DOM elements
|
||||
element = delegateElement = $( element );
|
||||
this.bindings = this.bindings.add( element );
|
||||
}
|
||||
// no element argument, shuffle and use this.element
|
||||
if ( !handlers ) {
|
||||
handlers = element;
|
||||
element = this.element;
|
||||
delegateElement = this.widget();
|
||||
} else {
|
||||
// accept selectors, DOM elements
|
||||
element = delegateElement = $( element );
|
||||
this.bindings = this.bindings.add( element );
|
||||
}
|
||||
|
||||
$.each( handlers, function( event, handler ) {
|
||||
function handlerProxy() {
|
||||
// allow widgets to customize the disabled handling
|
||||
// - disabled as an array instead of boolean
|
||||
// - disabled class as method for disabling individual parts
|
||||
if ( !suppressDisabledCheck &&
|
||||
( instance.options.disabled === true ||
|
||||
$( this ).hasClass( "ui-state-disabled" ) ) ) {
|
||||
return;
|
||||
}
|
||||
return ( typeof handler === "string" ? instance[ handler ] : handler )
|
||||
.apply( instance, arguments );
|
||||
}
|
||||
$.each( handlers, function( event, handler ) {
|
||||
function handlerProxy() {
|
||||
// allow widgets to customize the disabled handling
|
||||
// - disabled as an array instead of boolean
|
||||
// - disabled class as method for disabling individual parts
|
||||
if ( !suppressDisabledCheck &&
|
||||
( instance.options.disabled === true ||
|
||||
$( this ).hasClass( "ui-state-disabled" ) ) ) {
|
||||
return;
|
||||
}
|
||||
return ( typeof handler === "string" ? instance[ handler ] : handler )
|
||||
.apply( instance, arguments );
|
||||
}
|
||||
|
||||
// copy the guid so direct unbinding works
|
||||
if ( typeof handler !== "string" ) {
|
||||
handlerProxy.guid = handler.guid =
|
||||
handler.guid || handlerProxy.guid || $.guid++;
|
||||
}
|
||||
// copy the guid so direct unbinding works
|
||||
if ( typeof handler !== "string" ) {
|
||||
handlerProxy.guid = handler.guid =
|
||||
handler.guid || handlerProxy.guid || $.guid++;
|
||||
}
|
||||
|
||||
var match = event.match( /^(\w+)\s*(.*)$/ ),
|
||||
eventName = match[1] + instance.eventNamespace,
|
||||
selector = match[2];
|
||||
if ( selector ) {
|
||||
delegateElement.delegate( selector, eventName, handlerProxy );
|
||||
} else {
|
||||
element.bind( eventName, handlerProxy );
|
||||
}
|
||||
});
|
||||
},
|
||||
var match = event.match( /^(\w+)\s*(.*)$/ ),
|
||||
eventName = match[1] + instance.eventNamespace,
|
||||
selector = match[2];
|
||||
if ( selector ) {
|
||||
delegateElement.delegate( selector, eventName, handlerProxy );
|
||||
} else {
|
||||
element.bind( eventName, handlerProxy );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_off: function( element, eventName ) {
|
||||
eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
|
||||
element.unbind( eventName ).undelegate( eventName );
|
||||
},
|
||||
_off: function( element, eventName ) {
|
||||
eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
|
||||
element.unbind( eventName ).undelegate( eventName );
|
||||
},
|
||||
|
||||
_delay: function( handler, delay ) {
|
||||
function handlerProxy() {
|
||||
return ( typeof handler === "string" ? instance[ handler ] : handler )
|
||||
.apply( instance, arguments );
|
||||
}
|
||||
var instance = this;
|
||||
return setTimeout( handlerProxy, delay || 0 );
|
||||
},
|
||||
_delay: function( handler, delay ) {
|
||||
function handlerProxy() {
|
||||
return ( typeof handler === "string" ? instance[ handler ] : handler )
|
||||
.apply( instance, arguments );
|
||||
}
|
||||
var instance = this;
|
||||
return setTimeout( handlerProxy, delay || 0 );
|
||||
},
|
||||
|
||||
_hoverable: function( element ) {
|
||||
this.hoverable = this.hoverable.add( element );
|
||||
this._on( element, {
|
||||
mouseenter: function( event ) {
|
||||
$( event.currentTarget ).addClass( "ui-state-hover" );
|
||||
},
|
||||
mouseleave: function( event ) {
|
||||
$( event.currentTarget ).removeClass( "ui-state-hover" );
|
||||
}
|
||||
});
|
||||
},
|
||||
_hoverable: function( element ) {
|
||||
this.hoverable = this.hoverable.add( element );
|
||||
this._on( element, {
|
||||
mouseenter: function( event ) {
|
||||
$( event.currentTarget ).addClass( "ui-state-hover" );
|
||||
},
|
||||
mouseleave: function( event ) {
|
||||
$( event.currentTarget ).removeClass( "ui-state-hover" );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_focusable: function( element ) {
|
||||
this.focusable = this.focusable.add( element );
|
||||
this._on( element, {
|
||||
focusin: function( event ) {
|
||||
$( event.currentTarget ).addClass( "ui-state-focus" );
|
||||
},
|
||||
focusout: function( event ) {
|
||||
$( event.currentTarget ).removeClass( "ui-state-focus" );
|
||||
}
|
||||
});
|
||||
},
|
||||
_focusable: function( element ) {
|
||||
this.focusable = this.focusable.add( element );
|
||||
this._on( element, {
|
||||
focusin: function( event ) {
|
||||
$( event.currentTarget ).addClass( "ui-state-focus" );
|
||||
},
|
||||
focusout: function( event ) {
|
||||
$( event.currentTarget ).removeClass( "ui-state-focus" );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_trigger: function( type, event, data ) {
|
||||
var prop, orig,
|
||||
callback = this.options[ type ];
|
||||
_trigger: function( type, event, data ) {
|
||||
var prop, orig,
|
||||
callback = this.options[ type ];
|
||||
|
||||
data = data || {};
|
||||
event = $.Event( event );
|
||||
event.type = ( type === this.widgetEventPrefix ?
|
||||
type :
|
||||
this.widgetEventPrefix + type ).toLowerCase();
|
||||
// the original event may come from any element
|
||||
// so we need to reset the target on the new event
|
||||
event.target = this.element[ 0 ];
|
||||
data = data || {};
|
||||
event = $.Event( event );
|
||||
event.type = ( type === this.widgetEventPrefix ?
|
||||
type :
|
||||
this.widgetEventPrefix + type ).toLowerCase();
|
||||
// the original event may come from any element
|
||||
// so we need to reset the target on the new event
|
||||
event.target = this.element[ 0 ];
|
||||
|
||||
// copy original event properties over to the new event
|
||||
orig = event.originalEvent;
|
||||
if ( orig ) {
|
||||
for ( prop in orig ) {
|
||||
if ( !( prop in event ) ) {
|
||||
event[ prop ] = orig[ prop ];
|
||||
}
|
||||
}
|
||||
}
|
||||
// copy original event properties over to the new event
|
||||
orig = event.originalEvent;
|
||||
if ( orig ) {
|
||||
for ( prop in orig ) {
|
||||
if ( !( prop in event ) ) {
|
||||
event[ prop ] = orig[ prop ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.element.trigger( event, data );
|
||||
return !( $.isFunction( callback ) &&
|
||||
callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
|
||||
event.isDefaultPrevented() );
|
||||
}
|
||||
this.element.trigger( event, data );
|
||||
return !( $.isFunction( callback ) &&
|
||||
callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
|
||||
event.isDefaultPrevented() );
|
||||
}
|
||||
};
|
||||
|
||||
$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
|
||||
$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
|
||||
if ( typeof options === "string" ) {
|
||||
options = { effect: options };
|
||||
}
|
||||
var hasOptions,
|
||||
effectName = !options ?
|
||||
method :
|
||||
options === true || typeof options === "number" ?
|
||||
defaultEffect :
|
||||
options.effect || defaultEffect;
|
||||
options = options || {};
|
||||
if ( typeof options === "number" ) {
|
||||
options = { duration: options };
|
||||
}
|
||||
hasOptions = !$.isEmptyObject( options );
|
||||
options.complete = callback;
|
||||
if ( options.delay ) {
|
||||
element.delay( options.delay );
|
||||
}
|
||||
if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
|
||||
element[ method ]( options );
|
||||
} else if ( effectName !== method && element[ effectName ] ) {
|
||||
element[ effectName ]( options.duration, options.easing, callback );
|
||||
} else {
|
||||
element.queue(function( next ) {
|
||||
$( this )[ method ]();
|
||||
if ( callback ) {
|
||||
callback.call( element[ 0 ] );
|
||||
}
|
||||
next();
|
||||
});
|
||||
}
|
||||
};
|
||||
$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
|
||||
if ( typeof options === "string" ) {
|
||||
options = { effect: options };
|
||||
}
|
||||
var hasOptions,
|
||||
effectName = !options ?
|
||||
method :
|
||||
options === true || typeof options === "number" ?
|
||||
defaultEffect :
|
||||
options.effect || defaultEffect;
|
||||
options = options || {};
|
||||
if ( typeof options === "number" ) {
|
||||
options = { duration: options };
|
||||
}
|
||||
hasOptions = !$.isEmptyObject( options );
|
||||
options.complete = callback;
|
||||
if ( options.delay ) {
|
||||
element.delay( options.delay );
|
||||
}
|
||||
if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
|
||||
element[ method ]( options );
|
||||
} else if ( effectName !== method && element[ effectName ] ) {
|
||||
element[ effectName ]( options.duration, options.easing, callback );
|
||||
} else {
|
||||
element.queue(function( next ) {
|
||||
$( this )[ method ]();
|
||||
if ( callback ) {
|
||||
callback.call( element[ 0 ] );
|
||||
}
|
||||
next();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
@@ -19,23 +19,23 @@ CONDITIONS OF ANY KIND, either express or implied. See the Apache License and th
|
||||
the specific language governing permissions and limitations under the Apache License and the GPL License.
|
||||
*/
|
||||
(function ($) {
|
||||
if(typeof $.fn.each2 == "undefined"){
|
||||
$.fn.extend({
|
||||
/*
|
||||
* 4-10 times faster .each replacement
|
||||
* use it carefully, as it overrides jQuery context of element on each iteration
|
||||
*/
|
||||
each2 : function (c) {
|
||||
var j = $([0]), i = -1, l = this.length;
|
||||
while (
|
||||
++i < l
|
||||
&& (j.context = j[0] = this[i])
|
||||
&& c.call(j[0], i, j) !== false //"this"=DOM, i=index, j=jQuery object
|
||||
);
|
||||
return this;
|
||||
}
|
||||
});
|
||||
}
|
||||
if(typeof $.fn.each2 == "undefined"){
|
||||
$.fn.extend({
|
||||
/*
|
||||
* 4-10 times faster .each replacement
|
||||
* use it carefully, as it overrides jQuery context of element on each iteration
|
||||
*/
|
||||
each2 : function (c) {
|
||||
var j = $([0]), i = -1, l = this.length;
|
||||
while (
|
||||
++i < l
|
||||
&& (j.context = j[0] = this[i])
|
||||
&& c.call(j[0], i, j) !== false //"this"=DOM, i=index, j=jQuery object
|
||||
);
|
||||
return this;
|
||||
}
|
||||
});
|
||||
}
|
||||
})(jQuery);
|
||||
|
||||
(function ($, undefined) {
|
||||
@@ -182,7 +182,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
||||
* the elements under the pointer are scrolled.
|
||||
*/
|
||||
function installFilteredMouseMove(element) {
|
||||
element.bind("mousemove", function (e) {
|
||||
element.bind("mousemove", function (e) {
|
||||
var lastpos = lastMousePosition;
|
||||
if (lastpos === undefined || lastpos.x !== e.pageX || lastpos.y !== e.pageY) {
|
||||
$(e.target).trigger("mousemove-filtered", e);
|
||||
@@ -243,21 +243,21 @@ the specific language governing permissions and limitations under the Apache Lic
|
||||
|
||||
function measureTextWidth(e) {
|
||||
if (!sizer){
|
||||
var style = e[0].currentStyle || window.getComputedStyle(e[0], null);
|
||||
sizer = $("<div></div>").css({
|
||||
position: "absolute",
|
||||
left: "-10000px",
|
||||
top: "-10000px",
|
||||
display: "none",
|
||||
fontSize: style.fontSize,
|
||||
fontFamily: style.fontFamily,
|
||||
fontStyle: style.fontStyle,
|
||||
fontWeight: style.fontWeight,
|
||||
letterSpacing: style.letterSpacing,
|
||||
textTransform: style.textTransform,
|
||||
whiteSpace: "nowrap"
|
||||
});
|
||||
$("body").append(sizer);
|
||||
var style = e[0].currentStyle || window.getComputedStyle(e[0], null);
|
||||
sizer = $("<div></div>").css({
|
||||
position: "absolute",
|
||||
left: "-10000px",
|
||||
top: "-10000px",
|
||||
display: "none",
|
||||
fontSize: style.fontSize,
|
||||
fontFamily: style.fontFamily,
|
||||
fontStyle: style.fontStyle,
|
||||
fontWeight: style.fontWeight,
|
||||
letterSpacing: style.letterSpacing,
|
||||
textTransform: style.textTransform,
|
||||
whiteSpace: "nowrap"
|
||||
});
|
||||
$("body").append(sizer);
|
||||
}
|
||||
sizer.text(e.val());
|
||||
return sizer.width();
|
||||
@@ -1135,7 +1135,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
||||
highlightUnderEvent: function (event) {
|
||||
var el = $(event.target).closest(".select2-result-selectable");
|
||||
if (el.length > 0 && !el.is(".select2-highlighted")) {
|
||||
var choices = this.results.find('.select2-result-selectable');
|
||||
var choices = this.results.find('.select2-result-selectable');
|
||||
this.highlight(choices.index(el));
|
||||
} else if (el.length == 0) {
|
||||
// if we are over an unselectable item remove al highlights
|
||||
@@ -1219,8 +1219,8 @@ the specific language governing permissions and limitations under the Apache Lic
|
||||
if (opts.maximumSelectionSize >=1) {
|
||||
data = this.data();
|
||||
if ($.isArray(data) && data.length >= opts.maximumSelectionSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) {
|
||||
render("<li class='select2-selection-limit'>" + opts.formatSelectionTooBig(opts.maximumSelectionSize) + "</li>");
|
||||
return;
|
||||
render("<li class='select2-selection-limit'>" + opts.formatSelectionTooBig(opts.maximumSelectionSize) + "</li>");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1399,7 +1399,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
||||
|
||||
// single
|
||||
|
||||
createContainer: function () {
|
||||
createContainer: function () {
|
||||
var container = $("<div></div>", {
|
||||
"class": "select2-container"
|
||||
}).html([
|
||||
@@ -1789,7 +1789,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
||||
" <ul class='select2-results'>" ,
|
||||
" </ul>" ,
|
||||
"</div>"].join(""));
|
||||
return container;
|
||||
return container;
|
||||
},
|
||||
|
||||
// multi
|
||||
@@ -1984,7 +1984,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
||||
this.parent.opening.apply(this, arguments);
|
||||
|
||||
this.clearPlaceholder();
|
||||
this.resizeSearch();
|
||||
this.resizeSearch();
|
||||
this.focusSearch();
|
||||
},
|
||||
|
||||
@@ -2171,7 +2171,7 @@ the specific language governing permissions and limitations under the Apache Lic
|
||||
resizeSearch: function () {
|
||||
|
||||
var minimumWidth, left, maxWidth, containerLeft, searchWidth,
|
||||
sideBorderPadding = getSideBorderPadding(this.search);
|
||||
sideBorderPadding = getSideBorderPadding(this.search);
|
||||
|
||||
minimumWidth = measureTextWidth(this.search) + 10;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ requirejs.config({
|
||||
site: 'app/site',
|
||||
jquery: 'lib/jquery',
|
||||
backbone: 'lib/backbone',
|
||||
'backbone.relational': 'lib/backbone.relational',
|
||||
'backbone-associations': 'lib/backbone.associations',
|
||||
'backbone.syphon': 'lib/backbone.syphon',
|
||||
marionette: 'lib/backbone.marionette',
|
||||
bootstrap: 'lib/bootstrap',
|
||||
@@ -59,6 +59,10 @@ requirejs.config({
|
||||
exports: 'Backbone',
|
||||
deps: ['jquery', 'underscore']
|
||||
},
|
||||
'backbone-associations': {
|
||||
exports: 'Backbone.AssociatedModel',
|
||||
deps: ['backbone']
|
||||
},
|
||||
bootstrap: {
|
||||
exports: 'bootstrap',
|
||||
deps: ['jquery']
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</div>
|
||||
<div class="row well-sm">
|
||||
<section id="mix-comment">
|
||||
<div class="input-group">
|
||||
<div class="input-group" id="comment-input">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-sm btn-default"
|
||||
id="btn-add-comment"
|
||||
@@ -14,20 +14,20 @@
|
||||
Add comment!
|
||||
</button>
|
||||
</span>
|
||||
<input class="form-control input-mask-date" type="text" id="comment-text" name="new-comment">
|
||||
<input class="form-control" type="text" id="comment-text" name="new-comment">
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="row">
|
||||
<section id="mix-detail-section">
|
||||
<ul id="mix-tab" class="nav nav-tabs" data-tabs="tabs">
|
||||
<li class="active">
|
||||
<li class="active" id="tab-description">
|
||||
<a data-bypass="true" href="#description" data-toggle="tab">
|
||||
<i class="orange icon-terminal bigger-120"></i>
|
||||
Description
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<li id="tab-comments">
|
||||
<a data-bypass="true" href="#comments" data-toggle="tab">
|
||||
<i class="orange icon-comments bigger-120"></i>
|
||||
Comments
|
||||
|
||||
Reference in New Issue
Block a user