Annotations
authorCharles Connell <charles@connells.org>
Sat, 5 Apr 2014 20:10:21 +0000 (16:10 -0400)
committerCharles Connell <charles@connells.org>
Sat, 5 Apr 2014 20:10:21 +0000 (16:10 -0400)
19 files changed:
karmaworld/apps/notes/views.py
karmaworld/apps/quizzes/migrations/0002_rename_flashcard_fields.py [deleted file]
karmaworld/apps/quizzes/migrations/0003_auto__add_field_keyword_ranges.py [new file with mode: 0644]
karmaworld/apps/quizzes/migrations/0004_auto__del_unique_keyword_word_note__add_unique_keyword_word_note_range.py [new file with mode: 0644]
karmaworld/apps/quizzes/models.py
karmaworld/apps/quizzes/views.py
karmaworld/assets/css/annotator.min.css [new file with mode: 0644]
karmaworld/assets/js/annotator-full.min.js [new file with mode: 0644]
karmaworld/assets/js/foundation.joyride.js [new file with mode: 0644]
karmaworld/assets/js/jquery.cookie.js [new file with mode: 0644]
karmaworld/assets/js/note-detail.js
karmaworld/settings/dev.py
karmaworld/templates/base.html
karmaworld/templates/notes/note_detail.html
karmaworld/templates/user_profile.html
karmaworld/urls.py
karmaworld/utils/__init__.py
karmaworld/utils/ajax_increment.py [deleted file]
karmaworld/utils/ajax_utils.py [new file with mode: 0644]

index db274a4d75d74cd549d0bbdc172ff7e8b453e3e8..b9be9b55818df930ad38342662d12b7bc40359b8 100644 (file)
@@ -11,7 +11,7 @@ from django.core.exceptions import ObjectDoesNotExist
 from karmaworld.apps.courses.models import Course
 from karmaworld.apps.notes.search import SearchIndex
 from karmaworld.apps.users.models import NoteKarmaEvent
-from karmaworld.utils.ajax_increment import *
+from karmaworld.utils.ajax_utils import *
 
 import os
 
@@ -235,7 +235,8 @@ def process_downloaded_note(request_user, note):
 
 def downloaded_note(request, pk):
     """Record that somebody has flagged a note."""
-    return ajax_base(Note, request, pk, process_downloaded_note)
+    return ajax_pk_base(Note, request, pk, process_downloaded_note)
+
 
 def edit_note_tags(request, pk):
     """
diff --git a/karmaworld/apps/quizzes/migrations/0002_rename_flashcard_fields.py b/karmaworld/apps/quizzes/migrations/0002_rename_flashcard_fields.py
deleted file mode 100644 (file)
index 854d6ce..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-# -*- 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):
-        db.rename_column(u'quizzes_flashcardquestion', 'sideA', 'keyword_side')
-        db.rename_column(u'quizzes_flashcardquestion', 'sideB', 'definition_side')
-
-
-    def backwards(self, orm):
-        db.rename_column(u'quizzes_flashcardquestion', 'keyword_side', 'sideA')
-        db.rename_column(u'quizzes_flashcardquestion', 'definition_side', 'sideB')
diff --git a/karmaworld/apps/quizzes/migrations/0003_auto__add_field_keyword_ranges.py b/karmaworld/apps/quizzes/migrations/0003_auto__add_field_keyword_ranges.py
new file mode 100644 (file)
index 0000000..e7a8c79
--- /dev/null
@@ -0,0 +1,198 @@
+# -*- 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):
+        # Adding field 'Keyword.ranges'
+        db.add_column(u'quizzes_keyword', 'ranges',
+                      self.gf('django.db.models.fields.CharField')(max_length=1024, null=True, blank=True),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting field 'Keyword.ranges'
+        db.delete_column(u'quizzes_keyword', 'ranges')
+
+
+    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'})
+        },
+        u'courses.course': {
+            'Meta': {'ordering': "['-file_count', 'school', 'name']", 'unique_together': "(('name', 'school'),)", 'object_name': 'Course'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'department': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['courses.Department']", 'null': 'True', 'blank': 'True'}),
+            'desc': ('django.db.models.fields.TextField', [], {'max_length': '511', 'null': 'True', 'blank': 'True'}),
+            'file_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'flags': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'instructor_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+            'instructor_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'school': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['courses.School']", 'null': 'True', 'blank': 'True'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150', 'null': 'True'}),
+            'updated_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}),
+            'url': ('django.db.models.fields.URLField', [], {'max_length': '511', 'null': 'True', 'blank': 'True'})
+        },
+        u'courses.department': {
+            'Meta': {'unique_together': "(('name', 'school'),)", 'object_name': 'Department'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'school': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['courses.School']"}),
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150', 'null': 'True'}),
+            'url': ('django.db.models.fields.URLField', [], {'max_length': '511', 'null': 'True', 'blank': 'True'})
+        },
+        u'courses.school': {
+            'Meta': {'ordering': "['-file_count', '-priority', 'name']", 'object_name': 'School'},
+            'alias': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'facebook_id': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'file_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'hashtag': ('django.db.models.fields.CharField', [], {'max_length': '16', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'priority': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150', 'null': 'True'}),
+            'url': ('django.db.models.fields.URLField', [], {'max_length': '511', 'blank': 'True'}),
+            'usde_id': ('django.db.models.fields.BigIntegerField', [], {'unique': 'True', 'null': 'True', 'blank': 'True'})
+        },
+        u'licenses.license': {
+            'Meta': {'object_name': 'License'},
+            'html': ('django.db.models.fields.TextField', [], {}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'})
+        },
+        u'notes.note': {
+            'Meta': {'ordering': "['-uploaded_at']", 'unique_together': "(('fp_file', 'upstream_link'),)", 'object_name': 'Note'},
+            'course': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['courses.Course']"}),
+            'file_type': ('django.db.models.fields.CharField', [], {'default': "'???'", 'max_length': '15', 'null': 'True', 'blank': 'True'}),
+            'flags': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'fp_file': ('django_filepicker.models.FPFileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+            'gdrive_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'html': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'is_hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'license': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['licenses.License']", 'null': 'True', 'blank': 'True'}),
+            'mimetype': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'pdf_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}),
+            'static_html': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'text': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'thanks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'tweeted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow', 'null': 'True'}),
+            'upstream_link': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
+            'year': ('django.db.models.fields.IntegerField', [], {'default': '2014', 'null': 'True', 'blank': 'True'})
+        },
+        u'quizzes.flashcardquestion': {
+            'Meta': {'object_name': 'FlashCardQuestion'},
+            'category': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'definition_side': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
+            'difficulty': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'explanation': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'keyword_side': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
+            'quiz': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['quizzes.Quiz']"}),
+            'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'})
+        },
+        u'quizzes.keyword': {
+            'Meta': {'unique_together': "(('word', 'note'),)", 'object_name': 'Keyword'},
+            'definition': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'note': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['notes.Note']", 'null': 'True', 'blank': 'True'}),
+            'ranges': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}),
+            'word': ('django.db.models.fields.CharField', [], {'max_length': '1024'})
+        },
+        u'quizzes.multiplechoiceoption': {
+            'Meta': {'object_name': 'MultipleChoiceOption'},
+            'correct': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'choices'", 'to': u"orm['quizzes.MultipleChoiceQuestion']"}),
+            'text': ('django.db.models.fields.CharField', [], {'max_length': '2048'})
+        },
+        u'quizzes.multiplechoicequestion': {
+            'Meta': {'object_name': 'MultipleChoiceQuestion'},
+            'category': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'difficulty': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'explanation': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'question_text': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
+            'quiz': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['quizzes.Quiz']"}),
+            'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'})
+        },
+        u'quizzes.quiz': {
+            'Meta': {'object_name': 'Quiz'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
+            'note': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['notes.Note']", 'null': 'True', 'blank': 'True'}),
+            'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'})
+        },
+        u'quizzes.truefalsequestion': {
+            'Meta': {'object_name': 'TrueFalseQuestion'},
+            'category': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'difficulty': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'explanation': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'quiz': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['quizzes.Quiz']"}),
+            'text': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
+            'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}),
+            'true': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
+        },
+        u'taggit.tag': {
+            'Meta': {'object_name': 'Tag'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
+        },
+        u'taggit.taggeditem': {
+            'Meta': {'object_name': 'TaggedItem'},
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"})
+        }
+    }
+
+    complete_apps = ['quizzes']
\ No newline at end of file
diff --git a/karmaworld/apps/quizzes/migrations/0004_auto__del_unique_keyword_word_note__add_unique_keyword_word_note_range.py b/karmaworld/apps/quizzes/migrations/0004_auto__del_unique_keyword_word_note__add_unique_keyword_word_note_range.py
new file mode 100644 (file)
index 0000000..a13ebbc
--- /dev/null
@@ -0,0 +1,202 @@
+# -*- 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):
+        # Removing unique constraint on 'Keyword', fields ['word', 'note']
+        db.delete_unique(u'quizzes_keyword', ['word', 'note_id'])
+
+        # Adding unique constraint on 'Keyword', fields ['word', 'note', 'ranges']
+        db.create_unique(u'quizzes_keyword', ['word', 'note_id', 'ranges'])
+
+
+    def backwards(self, orm):
+        # Removing unique constraint on 'Keyword', fields ['word', 'note', 'ranges']
+        db.delete_unique(u'quizzes_keyword', ['word', 'note_id', 'ranges'])
+
+        # Adding unique constraint on 'Keyword', fields ['word', 'note']
+        db.create_unique(u'quizzes_keyword', ['word', 'note_id'])
+
+
+    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'})
+        },
+        u'courses.course': {
+            'Meta': {'ordering': "['-file_count', 'school', 'name']", 'unique_together': "(('name', 'school'),)", 'object_name': 'Course'},
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'department': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['courses.Department']", 'null': 'True', 'blank': 'True'}),
+            'desc': ('django.db.models.fields.TextField', [], {'max_length': '511', 'null': 'True', 'blank': 'True'}),
+            'file_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'flags': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'instructor_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+            'instructor_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'school': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['courses.School']", 'null': 'True', 'blank': 'True'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150', 'null': 'True'}),
+            'updated_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}),
+            'url': ('django.db.models.fields.URLField', [], {'max_length': '511', 'null': 'True', 'blank': 'True'})
+        },
+        u'courses.department': {
+            'Meta': {'unique_together': "(('name', 'school'),)", 'object_name': 'Department'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'school': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['courses.School']"}),
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150', 'null': 'True'}),
+            'url': ('django.db.models.fields.URLField', [], {'max_length': '511', 'null': 'True', 'blank': 'True'})
+        },
+        u'courses.school': {
+            'Meta': {'ordering': "['-file_count', '-priority', 'name']", 'object_name': 'School'},
+            'alias': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'facebook_id': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}),
+            'file_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'hashtag': ('django.db.models.fields.CharField', [], {'max_length': '16', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'location': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+            'priority': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '150', 'null': 'True'}),
+            'url': ('django.db.models.fields.URLField', [], {'max_length': '511', 'blank': 'True'}),
+            'usde_id': ('django.db.models.fields.BigIntegerField', [], {'unique': 'True', 'null': 'True', 'blank': 'True'})
+        },
+        u'licenses.license': {
+            'Meta': {'object_name': 'License'},
+            'html': ('django.db.models.fields.TextField', [], {}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'})
+        },
+        u'notes.note': {
+            'Meta': {'ordering': "['-uploaded_at']", 'unique_together': "(('fp_file', 'upstream_link'),)", 'object_name': 'Note'},
+            'course': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['courses.Course']"}),
+            'file_type': ('django.db.models.fields.CharField', [], {'default': "'???'", 'max_length': '15', 'null': 'True', 'blank': 'True'}),
+            'flags': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+            'fp_file': ('django_filepicker.models.FPFileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+            'gdrive_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'html': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
+            'is_hidden': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'license': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['licenses.License']", 'null': 'True', 'blank': 'True'}),
+            'mimetype': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
+            'pdf_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}),
+            'static_html': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'text': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'thanks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
+            'tweeted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow', 'null': 'True'}),
+            'upstream_link': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
+            'year': ('django.db.models.fields.IntegerField', [], {'default': '2014', 'null': 'True', 'blank': 'True'})
+        },
+        u'quizzes.flashcardquestion': {
+            'Meta': {'object_name': 'FlashCardQuestion'},
+            'category': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'definition_side': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
+            'difficulty': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'explanation': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'keyword_side': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
+            'quiz': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['quizzes.Quiz']"}),
+            'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'})
+        },
+        u'quizzes.keyword': {
+            'Meta': {'unique_together': "(('word', 'note', 'ranges'),)", 'object_name': 'Keyword'},
+            'definition': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'note': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['notes.Note']", 'null': 'True', 'blank': 'True'}),
+            'ranges': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}),
+            'word': ('django.db.models.fields.CharField', [], {'max_length': '1024'})
+        },
+        u'quizzes.multiplechoiceoption': {
+            'Meta': {'object_name': 'MultipleChoiceOption'},
+            'correct': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'question': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'choices'", 'to': u"orm['quizzes.MultipleChoiceQuestion']"}),
+            'text': ('django.db.models.fields.CharField', [], {'max_length': '2048'})
+        },
+        u'quizzes.multiplechoicequestion': {
+            'Meta': {'object_name': 'MultipleChoiceQuestion'},
+            'category': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'difficulty': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'explanation': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'question_text': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
+            'quiz': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['quizzes.Quiz']"}),
+            'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'})
+        },
+        u'quizzes.quiz': {
+            'Meta': {'object_name': 'Quiz'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}),
+            'note': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['notes.Note']", 'null': 'True', 'blank': 'True'}),
+            'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'})
+        },
+        u'quizzes.truefalsequestion': {
+            'Meta': {'object_name': 'TrueFalseQuestion'},
+            'category': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'difficulty': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
+            'explanation': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True', 'blank': 'True'}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'quiz': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['quizzes.Quiz']"}),
+            'text': ('django.db.models.fields.CharField', [], {'max_length': '2048'}),
+            'timestamp': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow'}),
+            'true': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
+        },
+        u'taggit.tag': {
+            'Meta': {'object_name': 'Tag'},
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
+        },
+        u'taggit.taggeditem': {
+            'Meta': {'object_name': 'TaggedItem'},
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}),
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"})
+        }
+    }
+
+    complete_apps = ['quizzes']
\ No newline at end of file
index 76753d7dc5290111f49b8b7e717f713740bf8b31..77a86a535c1bae90ff71c4754b93c891e63627bf 100644 (file)
@@ -11,10 +11,12 @@ class Keyword(models.Model):
 
     note = models.ForeignKey('notes.Note', blank=True, null=True)
 
+    ranges = models.CharField(max_length=1024, blank=True, null=True)
+
     timestamp = models.DateTimeField(default=datetime.datetime.utcnow)
 
     class Meta:
-        unique_together = ('word', 'note')
+        unique_together = ('word', 'note', 'ranges')
 
     def __unicode__(self):
         return self.word
index 80c98b543c954ef82dda53ef0bbaa0e87ccb212a..1e56f0f1ee83dd4a2adfacd1473f51c8fc2bb2c2 100644 (file)
@@ -15,7 +15,7 @@ from karmaworld.apps.notes.models import Note
 from karmaworld.apps.quizzes.forms import KeywordForm
 from karmaworld.apps.quizzes.models import Quiz, ALL_QUESTION_CLASSES, Keyword, BaseQuizQuestion, \
     ALL_QUESTION_CLASSES_NAMES, MultipleChoiceQuestion, MultipleChoiceOption, TrueFalseQuestion, FlashCardQuestion
-from karmaworld.utils import ajax_base
+from karmaworld.utils import ajax_pk_base, ajax_base
 
 
 class QuizView(DetailView):
@@ -125,4 +125,66 @@ def quiz_answer(request):
                                                   'exception': e.__class__.__name__}),
                                       mimetype="application/json")
 
-    return HttpResponse(json.dumps({'correct': correct}), mimetype="application/json")
\ No newline at end of file
+    return HttpResponse(json.dumps({'correct': correct}), mimetype="application/json")
+
+
+def set_keyword(annotation_uri, keyword, definition, ranges):
+    try:
+        keyword = Keyword.objects.get(note_id=annotation_uri, word=keyword, ranges=ranges)
+        keyword.definition = definition
+        keyword.save()
+    except ObjectDoesNotExist:
+        Keyword.objects.create(note_id=annotation_uri, word=keyword, definition=definition, ranges=ranges)
+
+
+def delete_keyword(annotation_uri, keyword, definition, ranges):
+    keyword = Keyword.objects.get(note_id=annotation_uri, word=keyword, definition=definition, ranges=ranges)
+    keyword.definition = definition
+    keyword.delete()
+
+
+def process_set_delete_keyword(request):
+    annotator_data = json.loads(request.raw_post_data)
+    annotation_uri = annotator_data['uri']
+    keyword = annotator_data['quote']
+    definition = annotator_data['text']
+    ranges = json.dumps(annotator_data['ranges'])
+
+    try:
+        if request.method in ('POST', 'PUT'):
+            set_keyword(annotation_uri, keyword, definition, ranges)
+        elif request.method == 'DELETE':
+            delete_keyword(annotation_uri, keyword, definition, ranges)
+    except Exception, e:
+        return HttpResponseNotFound(json.dumps({'status': 'fail', 'message': e.message}),
+                                    mimetype="application/json")
+
+
+def set_delete_keyword(request):
+    return ajax_base(request, process_set_delete_keyword, ('POST', 'PUT', 'DELETE'))
+
+
+def get_keywords(request):
+    annotation_uri = request.GET['uri']
+
+    try:
+        keywords = Keyword.objects.filter(note_id=annotation_uri).exclude(ranges=None)
+        keywords_data = {
+            'total': len(keywords),
+            'rows': []
+        }
+        for keyword in keywords:
+            keyword_data = {
+                'quote': keyword.word,
+                'text': keyword.definition,
+                'ranges': json.loads(keyword.ranges),
+                'created': keyword.timestamp.isoformat(),
+            }
+            keywords_data['rows'].append(keyword_data)
+
+        return HttpResponse(json.dumps(keywords_data), mimetype='application/json')
+
+    except ObjectDoesNotExist, e:
+        return HttpResponseNotFound(json.dumps({'status': 'fail', 'message': e.message}),
+                                    mimetype="application/json")
+
diff --git a/karmaworld/assets/css/annotator.min.css b/karmaworld/assets/css/annotator.min.css
new file mode 100644 (file)
index 0000000..0584acf
--- /dev/null
@@ -0,0 +1 @@
+.annotator-notice,.annotator-filter *,.annotator-widget *{font-family:"Helvetica Neue",Arial,Helvetica,sans-serif;font-weight:normal;text-align:left;margin:0;padding:0;background:0;-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none;-moz-box-shadow:none;-webkit-box-shadow:none;-o-box-shadow:none;box-shadow:none;color:#909090}.annotator-adder{background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAAAwCAYAAAD+WvNWAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowMzgwMTE3NDA3MjA2ODExODRCQUU5RDY0RTkyQTJDNiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDowOUY5RUFERDYwOEIxMUUxOTQ1RDkyQzU2OTNEMDZENCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDowOUY5RUFEQzYwOEIxMUUxOTQ1RDkyQzU2OTNEMDZENCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1hY2ludG9zaCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjA1ODAxMTc0MDcyMDY4MTE5MTA5OUIyNDhFRUQ1QkM4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjAzODAxMTc0MDcyMDY4MTE4NEJBRTlENjRFOTJBMkM2Ii8+IDwvcmRmOkRlc2NyaXB0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');background-repeat:no-repeat}.annotator-resize,.annotator-widget::after,.annotator-editor a::after,.annotator-viewer .annotator-controls button,.annotator-viewer .annotator-controls a,.annotator-filter .annotator-filter-navigation button::after,.annotator-filter .annotator-filter-property .annotator-filter-clear{background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAEiCAYAAAD0w4JOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RDY0MTMzNTM2QUQzMTFFMUE2REJERDgwQTM3Njg5NTUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RDY0MTMzNTQ2QUQzMTFFMUE2REJERDgwQTM3Njg5NTUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2ODkwQjlFQzZBRDExMUUxQTZEQkREODBBMzc2ODk1NSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpENjQxMzM1MjZBRDMxMUUxQTZEQkREODBBMzc2ODk1NSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkijPpwAABBRSURBVHja7JsJVBRX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');background-repeat:no-repeat}.annotator-hl{background:rgba(255,255,10,0.3)}.annotator-hl-temporary{background:rgba(0,124,255,0.3)}.annotator-wrapper{position:relative}.annotator-adder,.annotator-outer,.annotator-notice{z-index:1020}.annotator-filter{z-index:1010}.annotator-adder,.annotator-outer,.annotator-widget,.annotator-notice{position:absolute;font-size:10px;line-height:1}.annotator-hide{display:none;visibility:hidden}.annotator-adder{margin-top:-48px;margin-left:-24px;width:48px;height:48px;background-position:left top}.annotator-adder:hover{background-position:center top}.annotator-adder:active{background-position:center right}.annotator-adder button{display:block;width:36px;height:41px;margin:0 auto;border:0;background:0;text-indent:-999em;cursor:pointer}.annotator-outer{width:0;height:0}.annotator-widget{margin:0;padding:0;bottom:15px;left:-18px;min-width:265px;background-color:rgba(251,251,251,0.98);border:1px solid rgba(122,122,122,0.6);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 15px rgba(0,0,0,0.2);-o-box-shadow:0 5px 15px rgba(0,0,0,0.2);box-shadow:0 5px 15px rgba(0,0,0,0.2)}.annotator-invert-x .annotator-widget{left:auto;right:-18px}.annotator-invert-y .annotator-widget{bottom:auto;top:8px}.annotator-widget strong{font-weight:bold}.annotator-widget .annotator-listing,.annotator-widget .annotator-item{padding:0;margin:0;list-style:none}.annotator-widget::after{content:"";display:block;width:18px;height:10px;background-position:0 0;position:absolute;bottom:-10px;left:8px}.annotator-invert-x .annotator-widget::after{left:auto;right:8px}.annotator-invert-y .annotator-widget::after{background-position:0 -15px;bottom:auto;top:-9px}.annotator-widget .annotator-item,.annotator-editor .annotator-item input,.annotator-editor .annotator-item textarea{position:relative;font-size:12px}.annotator-viewer .annotator-item{border-top:2px solid rgba(122,122,122,0.2)}.annotator-widget .annotator-item:first-child{border-top:0}.annotator-editor .annotator-item,.annotator-viewer div{border-top:1px solid rgba(133,133,133,0.11)}.annotator-viewer div{padding:6px 6px}.annotator-viewer .annotator-item ol,.annotator-viewer .annotator-item ul{padding:4px 16px}.annotator-viewer div:first-of-type,.annotator-editor .annotator-item:first-child textarea{padding-top:12px;padding-bottom:12px;color:#3c3c3c;font-size:13px;font-style:italic;line-height:1.3;border-top:0}.annotator-viewer .annotator-controls{position:relative;top:5px;right:5px;padding-left:5px;opacity:0;-webkit-transition:opacity .2s ease-in;-moz-transition:opacity .2s ease-in;-o-transition:opacity .2s ease-in;transition:opacity .2s ease-in;float:right}.annotator-viewer li:hover .annotator-controls,.annotator-viewer li .annotator-controls.annotator-visible{opacity:1}.annotator-viewer .annotator-controls button,.annotator-viewer .annotator-controls a{cursor:pointer;display:inline-block;width:13px;height:13px;margin-left:2px;border:0;opacity:.2;text-indent:-900em;background-color:transparent;outline:0}.annotator-viewer .annotator-controls button:hover,.annotator-viewer .annotator-controls button:focus,.annotator-viewer .annotator-controls a:hover,.annotator-viewer .annotator-controls a:focus{opacity:.9}.annotator-viewer .annotator-controls button:active,.annotator-viewer .annotator-controls a:active{opacity:1}.annotator-viewer .annotator-controls button[disabled]{display:none}.annotator-viewer .annotator-controls .annotator-edit{background-position:0 -60px}.annotator-viewer .annotator-controls .annotator-delete{background-position:0 -75px}.annotator-viewer .annotator-controls .annotator-link{background-position:0 -270px}.annotator-editor .annotator-item{position:relative}.annotator-editor .annotator-item label{top:0;display:inline;cursor:pointer;font-size:12px}.annotator-editor .annotator-item input,.annotator-editor .annotator-item textarea{display:block;min-width:100%;padding:10px 8px;border:0;margin:0;color:#3c3c3c;background:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box;resize:none}.annotator-editor .annotator-item textarea::-webkit-scrollbar{height:8px;width:8px}.annotator-editor .annotator-item textarea::-webkit-scrollbar-track-piece{margin:13px 0 3px;background-color:#e5e5e5;-webkit-border-radius:4px}.annotator-editor .annotator-item textarea::-webkit-scrollbar-thumb:vertical{height:25px;background-color:#ccc;-webkit-border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.1)}.annotator-editor .annotator-item textarea::-webkit-scrollbar-thumb:horizontal{width:25px;background-color:#ccc;-webkit-border-radius:4px}.annotator-editor .annotator-item:first-child textarea{min-height:5.5em;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;-o-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.annotator-editor .annotator-item input:focus,.annotator-editor .annotator-item textarea:focus{background-color:#f3f3f3;outline:0}.annotator-editor .annotator-item input[type=radio],.annotator-editor .annotator-item input[type=checkbox]{width:auto;min-width:0;padding:0;display:inline;margin:0 4px 0 0;cursor:pointer}.annotator-editor .annotator-checkbox{padding:8px 6px}.annotator-filter,.annotator-filter .annotator-filter-navigation button,.annotator-editor .annotator-controls{text-align:right;padding:3px;border-top:1px solid #d4d4d4;background-color:#d4d4d4;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),color-stop(0.6,#dcdcdc),to(#d2d2d2));background-image:-moz-linear-gradient(to bottom,#f5f5f5,#dcdcdc 60%,#d2d2d2);background-image:-webkit-linear-gradient(to bottom,#f5f5f5,#dcdcdc 60%,#d2d2d2);background-image:linear-gradient(to bottom,#f5f5f5,#dcdcdc 60%,#d2d2d2);-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.7),inset -1px 0 0 rgba(255,255,255,0.7),inset 0 1px 0 rgba(255,255,255,0.7);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.7),inset -1px 0 0 rgba(255,255,255,0.7),inset 0 1px 0 rgba(255,255,255,0.7);-o-box-shadow:inset 1px 0 0 rgba(255,255,255,0.7),inset -1px 0 0 rgba(255,255,255,0.7),inset 0 1px 0 rgba(255,255,255,0.7);box-shadow:inset 1px 0 0 rgba(255,255,255,0.7),inset -1px 0 0 rgba(255,255,255,0.7),inset 0 1px 0 rgba(255,255,255,0.7);-webkit-border-radius:0 0 5px 5px;-moz-border-radius:0 0 5px 5px;-o-border-radius:0 0 5px 5px;border-radius:0 0 5px 5px}.annotator-editor.annotator-invert-y .annotator-controls{border-top:0;border-bottom:1px solid #b4b4b4;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;-o-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.annotator-editor a,.annotator-filter .annotator-filter-property label{position:relative;display:inline-block;padding:0 6px 0 22px;color:#363636;text-shadow:0 1px 0 rgba(255,255,255,0.75);text-decoration:none;line-height:24px;font-size:12px;font-weight:bold;border:1px solid #a2a2a2;background-color:#d4d4d4;background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),color-stop(0.5,#d2d2d2),color-stop(0.5,#bebebe),to(#d2d2d2));background-image:-moz-linear-gradient(to bottom,#f5f5f5,#d2d2d2 50%,#bebebe 50%,#d2d2d2);background-image:-webkit-linear-gradient(to bottom,#f5f5f5,#d2d2d2 50%,#bebebe 50%,#d2d2d2);background-image:linear-gradient(to bottom,#f5f5f5,#d2d2d2 50%,#bebebe 50%,#d2d2d2);-webkit-box-shadow:inset 0 0 5px rgba(255,255,255,0.2),inset 0 0 1px rgba(255,255,255,0.8);-moz-box-shadow:inset 0 0 5px rgba(255,255,255,0.2),inset 0 0 1px rgba(255,255,255,0.8);-o-box-shadow:inset 0 0 5px rgba(255,255,255,0.2),inset 0 0 1px rgba(255,255,255,0.8);box-shadow:inset 0 0 5px rgba(255,255,255,0.2),inset 0 0 1px rgba(255,255,255,0.8);-webkit-border-radius:5px;-moz-border-radius:5px;-o-border-radius:5px;border-radius:5px}.annotator-editor a::after{position:absolute;top:50%;left:5px;display:block;content:"";width:15px;height:15px;margin-top:-7px;background-position:0 -90px}.annotator-editor a:hover,.annotator-editor a:focus,.annotator-editor a.annotator-focus,.annotator-filter .annotator-filter-active label,.annotator-filter .annotator-filter-navigation button:hover{outline:0;border-color:#435aa0;background-color:#3865f9;background-image:-webkit-gradient(linear,left top,left bottom,from(#7691fb),color-stop(0.5,#5075fb),color-stop(0.5,#3865f9),to(#3665fa));background-image:-moz-linear-gradient(to bottom,#7691fb,#5075fb 50%,#3865f9 50%,#3665fa);background-image:-webkit-linear-gradient(to bottom,#7691fb,#5075fb 50%,#3865f9 50%,#3665fa);background-image:linear-gradient(to bottom,#7691fb,#5075fb 50%,#3865f9 50%,#3665fa);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.42)}.annotator-editor a:hover::after,.annotator-editor a:focus::after{margin-top:-8px;background-position:0 -105px}.annotator-editor a:active,.annotator-filter .annotator-filter-navigation button:active{border-color:#700c49;background-color:#d12e8e;background-image:-webkit-gradient(linear,left top,left bottom,from(#fc7cca),color-stop(0.5,#e85db2),color-stop(0.5,#d12e8e),to(#ff009c));background-image:-moz-linear-gradient(to bottom,#fc7cca,#e85db2 50%,#d12e8e 50%,#ff009c);background-image:-webkit-linear-gradient(to bottom,#fc7cca,#e85db2 50%,#d12e8e 50%,#ff009c);background-image:linear-gradient(to bottom,#fc7cca,#e85db2 50%,#d12e8e 50%,#ff009c)}.annotator-editor a.annotator-save::after{background-position:0 -120px}.annotator-editor a.annotator-save:hover::after,.annotator-editor a.annotator-save:focus::after,.annotator-editor a.annotator-save.annotator-focus::after{margin-top:-8px;background-position:0 -135px}.annotator-editor .annotator-widget::after{background-position:0 -30px}.annotator-editor.annotator-invert-y .annotator-widget .annotator-controls{background-color:#f2f2f2}.annotator-editor.annotator-invert-y .annotator-widget::after{background-position:0 -45px;height:11px}.annotator-resize{position:absolute;top:0;right:0;width:12px;height:12px;background-position:2px -150px}.annotator-invert-x .annotator-resize{right:auto;left:0;background-position:0 -195px}.annotator-invert-y .annotator-resize{top:auto;bottom:0;background-position:2px -165px}.annotator-invert-y.annotator-invert-x .annotator-resize{background-position:0 -180px}.annotator-notice{color:#fff;position:absolute;position:fixed;top:-54px;left:0;width:100%;font-size:14px;line-height:50px;text-align:center;background:black;background:rgba(0,0,0,0.9);border-bottom:4px solid #d4d4d4;-webkit-transition:top .4s ease-out;-moz-transition:top .4s ease-out;-o-transition:top .4s ease-out;transition:top .4s ease-out}.ie6 .annotator-notice{position:absolute}.annotator-notice-success{border-color:#3665f9}.annotator-notice-error{border-color:#ff7e00}.annotator-notice p{margin:0}.annotator-notice a{color:#fff}.annotator-notice-show{top:0}.annotator-tags{margin-bottom:-2px}.annotator-tags .annotator-tag{display:inline-block;padding:0 8px;margin-bottom:2px;line-height:1.6;font-weight:bold;background-color:#e6e6e6;-webkit-border-radius:8px;-moz-border-radius:8px;-o-border-radius:8px;border-radius:8px}.annotator-filter{position:fixed;top:0;right:0;left:0;text-align:left;line-height:0;border:0;border-bottom:1px solid #878787;padding-left:10px;padding-right:10px;-webkit-border-radius:0;-moz-border-radius:0;-o-border-radius:0;border-radius:0;-webkit-box-shadow:inset 0 -1px 0 rgba(255,255,255,0.3);-moz-box-shadow:inset 0 -1px 0 rgba(255,255,255,0.3);-o-box-shadow:inset 0 -1px 0 rgba(255,255,255,0.3);box-shadow:inset 0 -1px 0 rgba(255,255,255,0.3)}.annotator-filter strong{font-size:12px;font-weight:bold;color:#3c3c3c;text-shadow:0 1px 0 rgba(255,255,255,0.7);position:relative;top:-9px}.annotator-filter .annotator-filter-property,.annotator-filter .annotator-filter-navigation{position:relative;display:inline-block;overflow:hidden;line-height:10px;padding:2px 0;margin-right:8px}.annotator-filter .annotator-filter-property label,.annotator-filter .annotator-filter-navigation button{text-align:left;display:block;float:left;line-height:20px;-webkit-border-radius:10px 0 0 10px;-moz-border-radius:10px 0 0 10px;-o-border-radius:10px 0 0 10px;border-radius:10px 0 0 10px}.annotator-filter .annotator-filter-property label{padding-left:8px}.annotator-filter .annotator-filter-property input{display:block;float:right;-webkit-appearance:none;background-color:#fff;border:1px solid #878787;border-left:none;padding:2px 4px;line-height:16px;min-height:16px;font-size:12px;width:150px;color:#333;background-color:#f8f8f8;-webkit-border-radius:0 10px 10px 0;-moz-border-radius:0 10px 10px 0;-o-border-radius:0 10px 10px 0;border-radius:0 10px 10px 0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.2);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.2);-o-box-shadow:inset 0 1px 1px rgba(0,0,0,0.2);box-shadow:inset 0 1px 1px rgba(0,0,0,0.2)}.annotator-filter .annotator-filter-property input:focus{outline:0;background-color:#fff}.annotator-filter .annotator-filter-clear{position:absolute;right:3px;top:6px;border:0;text-indent:-900em;width:15px;height:15px;background-position:0 -90px;opacity:.4}.annotator-filter .annotator-filter-clear:hover,.annotator-filter .annotator-filter-clear:focus{opacity:.8}.annotator-filter .annotator-filter-clear:active{opacity:1}.annotator-filter .annotator-filter-navigation button{border:1px solid #a2a2a2;padding:0;text-indent:-900px;width:20px;min-height:22px;-webkit-box-shadow:inset 0 0 5px rgba(255,255,255,0.2),inset 0 0 1px rgba(255,255,255,0.8);-moz-box-shadow:inset 0 0 5px rgba(255,255,255,0.2),inset 0 0 1px rgba(255,255,255,0.8);-o-box-shadow:inset 0 0 5px rgba(255,255,255,0.2),inset 0 0 1px rgba(255,255,255,0.8);box-shadow:inset 0 0 5px rgba(255,255,255,0.2),inset 0 0 1px rgba(255,255,255,0.8)}.annotator-filter .annotator-filter-navigation button,.annotator-filter .annotator-filter-navigation button:hover,.annotator-filter .annotator-filter-navigation button:focus{color:transparent}.annotator-filter .annotator-filter-navigation button::after{position:absolute;top:8px;left:8px;content:"";display:block;width:9px;height:9px;background-position:0 -210px}.annotator-filter .annotator-filter-navigation button:hover::after{background-position:0 -225px}.annotator-filter .annotator-filter-navigation .annotator-filter-next{-webkit-border-radius:0 10px 10px 0;-moz-border-radius:0 10px 10px 0;-o-border-radius:0 10px 10px 0;border-radius:0 10px 10px 0;border-left:none}.annotator-filter .annotator-filter-navigation .annotator-filter-next::after{left:auto;right:7px;background-position:0 -240px}.annotator-filter .annotator-filter-navigation .annotator-filter-next:hover::after{background-position:0 -255px}.annotator-hl-active{background:rgba(255,255,10,0.8)}.annotator-hl-filtered{background-color:transparent}
\ No newline at end of file
diff --git a/karmaworld/assets/js/annotator-full.min.js b/karmaworld/assets/js/annotator-full.min.js
new file mode 100644 (file)
index 0000000..c27a43b
--- /dev/null
@@ -0,0 +1,19 @@
+
+/*
+** Annotator v1.2.9
+** https://github.com/okfn/annotator/
+**
+** Copyright 2013, the Annotator project contributors.
+** Dual licensed under the MIT and GPLv3 licenses.
+** https://github.com/okfn/annotator/blob/master/LICENSE
+**
+** Built at: 2013-12-02 17:58:01Z
+ */
+
+
+//
+
+!function(){var $,Annotator,Delegator,LinkParser,Range,Util,base64Decode,base64UrlDecode,createDateFromISO8601,findChild,fn,functions,g,getNodeName,getNodePosition,gettext,parseToken,simpleXPathJQuery,simpleXPathPure,_Annotator,_gettext,_i,_j,_len,_len1,_ref,_ref1,_t,__slice=[].slice,__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},__bind=function(fn,me){return function(){return fn.apply(me,arguments)}},__indexOf=[].indexOf||function(item){for(var i=0,l=this.length;i<l;i++){if(i in this&&this[i]===item)return i}return-1};simpleXPathJQuery=function(relativeRoot){var jq;jq=this.map(function(){var elem,idx,path,tagName;path="";elem=this;while((elem!=null?elem.nodeType:void 0)===Node.ELEMENT_NODE&&elem!==relativeRoot){tagName=elem.tagName.replace(":","\\:");idx=$(elem.parentNode).children(tagName).index(elem)+1;idx="["+idx+"]";path="/"+elem.tagName.toLowerCase()+idx+path;elem=elem.parentNode}return path});return jq.get()};simpleXPathPure=function(relativeRoot){var getPathSegment,getPathTo,jq,rootNode;getPathSegment=function(node){var name,pos;name=getNodeName(node);pos=getNodePosition(node);return""+name+"["+pos+"]"};rootNode=relativeRoot;getPathTo=function(node){var xpath;xpath="";while(node!==rootNode){if(node==null){throw new Error("Called getPathTo on a node which was not a descendant of @rootNode. "+rootNode)}xpath=getPathSegment(node)+"/"+xpath;node=node.parentNode}xpath="/"+xpath;xpath=xpath.replace(/\/$/,"");return xpath};jq=this.map(function(){var path;path=getPathTo(this);return path});return jq.get()};findChild=function(node,type,index){var child,children,found,name,_i,_len;if(!node.hasChildNodes()){throw new Error("XPath error: node has no children!")}children=node.childNodes;found=0;for(_i=0,_len=children.length;_i<_len;_i++){child=children[_i];name=getNodeName(child);if(name===type){found+=1;if(found===index){return child}}}throw new Error("XPath error: wanted child not found.")};getNodeName=function(node){var nodeName;nodeName=node.nodeName.toLowerCase();switch(nodeName){case"#text":return"text()";case"#comment":return"comment()";case"#cdata-section":return"cdata-section()";default:return nodeName}};getNodePosition=function(node){var pos,tmp;pos=0;tmp=node;while(tmp){if(tmp.nodeName===node.nodeName){pos++}tmp=tmp.previousSibling}return pos};gettext=null;if(typeof Gettext!=="undefined"&&Gettext!==null){_gettext=new Gettext({domain:"annotator"});gettext=function(msgid){return _gettext.gettext(msgid)}}else{gettext=function(msgid){return msgid}}_t=function(msgid){return gettext(msgid)};if(!(typeof jQuery!=="undefined"&&jQuery!==null?(_ref=jQuery.fn)!=null?_ref.jquery:void 0:void 0)){console.error(_t("Annotator requires jQuery: have you included lib/vendor/jquery.js?"))}if(!(JSON&&JSON.parse&&JSON.stringify)){console.error(_t("Annotator requires a JSON implementation: have you included lib/vendor/json2.js?"))}$=jQuery;Util={};Util.flatten=function(array){var flatten;flatten=function(ary){var el,flat,_i,_len;flat=[];for(_i=0,_len=ary.length;_i<_len;_i++){el=ary[_i];flat=flat.concat(el&&$.isArray(el)?flatten(el):el)}return flat};return flatten(array)};Util.contains=function(parent,child){var node;node=child;while(node!=null){if(node===parent){return true}node=node.parentNode}return false};Util.getTextNodes=function(jq){var getTextNodes;getTextNodes=function(node){var nodes;if(node&&node.nodeType!==Node.TEXT_NODE){nodes=[];if(node.nodeType!==Node.COMMENT_NODE){node=node.lastChild;while(node){nodes.push(getTextNodes(node));node=node.previousSibling}}return nodes.reverse()}else{return node}};return jq.map(function(){return Util.flatten(getTextNodes(this))})};Util.getLastTextNodeUpTo=function(n){var result;switch(n.nodeType){case Node.TEXT_NODE:return n;case Node.ELEMENT_NODE:if(n.lastChild!=null){result=Util.getLastTextNodeUpTo(n.lastChild);if(result!=null){return result}}break}n=n.previousSibling;if(n!=null){return Util.getLastTextNodeUpTo(n)}else{return null}};Util.getFirstTextNodeNotBefore=function(n){var result;switch(n.nodeType){case Node.TEXT_NODE:return n;case Node.ELEMENT_NODE:if(n.firstChild!=null){result=Util.getFirstTextNodeNotBefore(n.firstChild);if(result!=null){return result}}break}n=n.nextSibling;if(n!=null){return Util.getFirstTextNodeNotBefore(n)}else{return null}};Util.readRangeViaSelection=function(range){var sel;sel=Util.getGlobal().getSelection();sel.removeAllRanges();sel.addRange(range.toRange());return sel.toString()};Util.xpathFromNode=function(el,relativeRoot){var exception,result;try{result=simpleXPathJQuery.call(el,relativeRoot)}catch(_error){exception=_error;console.log("jQuery-based XPath construction failed! Falling back to manual.");result=simpleXPathPure.call(el,relativeRoot)}return result};Util.nodeFromXPath=function(xp,root){var idx,name,node,step,steps,_i,_len,_ref1;steps=xp.substring(1).split("/");node=root;for(_i=0,_len=steps.length;_i<_len;_i++){step=steps[_i];_ref1=step.split("["),name=_ref1[0],idx=_ref1[1];idx=idx!=null?parseInt((idx!=null?idx.split("]"):void 0)[0]):1;node=findChild(node,name.toLowerCase(),idx)}return node};Util.escape=function(html){return html.replace(/&(?!\w+;)/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")};Util.uuid=function(){var counter;counter=0;return function(){return counter++}}();Util.getGlobal=function(){return function(){return this}()};Util.maxZIndex=function($elements){var all,el;all=function(){var _i,_len,_results;_results=[];for(_i=0,_len=$elements.length;_i<_len;_i++){el=$elements[_i];if($(el).css("position")==="static"){_results.push(-1)}else{_results.push(parseInt($(el).css("z-index"),10)||-1)}}return _results}();return Math.max.apply(Math,all)};Util.mousePosition=function(e,offsetEl){var offset,_ref1;if((_ref1=$(offsetEl).css("position"))!=="absolute"&&_ref1!=="fixed"&&_ref1!=="relative"){offsetEl=$(offsetEl).offsetParent()[0]}offset=$(offsetEl).offset();return{top:e.pageY-offset.top,left:e.pageX-offset.left}};Util.preventEventDefault=function(event){return event!=null?typeof event.preventDefault==="function"?event.preventDefault():void 0:void 0};functions=["log","debug","info","warn","exception","assert","dir","dirxml","trace","group","groupEnd","groupCollapsed","time","timeEnd","profile","profileEnd","count","clear","table","error","notifyFirebug","firebug","userObjects"];if(typeof console!=="undefined"&&console!==null){if(console.group==null){console.group=function(name){return console.log("GROUP: ",name)}}if(console.groupCollapsed==null){console.groupCollapsed=console.group}for(_i=0,_len=functions.length;_i<_len;_i++){fn=functions[_i];if(console[fn]==null){console[fn]=function(){return console.log(_t("Not implemented:")+(" console."+name))}}}}else{this.console={};for(_j=0,_len1=functions.length;_j<_len1;_j++){fn=functions[_j];this.console[fn]=function(){}}this.console["error"]=function(){var args;args=1<=arguments.length?__slice.call(arguments,0):[];return alert("ERROR: "+args.join(", "))};this.console["warn"]=function(){var args;args=1<=arguments.length?__slice.call(arguments,0):[];return alert("WARNING: "+args.join(", "))}}Delegator=function(){Delegator.prototype.events={};Delegator.prototype.options={};Delegator.prototype.element=null;function Delegator(element,options){this.options=$.extend(true,{},this.options,options);this.element=$(element);this._closures={};this.on=this.subscribe;this.addEvents()}Delegator.prototype.addEvents=function(){var event,_k,_len2,_ref1,_results;_ref1=Delegator._parseEvents(this.events);_results=[];for(_k=0,_len2=_ref1.length;_k<_len2;_k++){event=_ref1[_k];_results.push(this._addEvent(event.selector,event.event,event.functionName))}return _results};Delegator.prototype.removeEvents=function(){var event,_k,_len2,_ref1,_results;_ref1=Delegator._parseEvents(this.events);_results=[];for(_k=0,_len2=_ref1.length;_k<_len2;_k++){event=_ref1[_k];_results.push(this._removeEvent(event.selector,event.event,event.functionName))}return _results};Delegator.prototype._addEvent=function(selector,event,functionName){var closure;closure=function(_this){return function(){return _this[functionName].apply(_this,arguments)}}(this);if(selector===""&&Delegator._isCustomEvent(event)){this.subscribe(event,closure)}else{this.element.delegate(selector,event,closure)}this._closures[""+selector+"/"+event+"/"+functionName]=closure;return this};Delegator.prototype._removeEvent=function(selector,event,functionName){var closure;closure=this._closures[""+selector+"/"+event+"/"+functionName];if(selector===""&&Delegator._isCustomEvent(event)){this.unsubscribe(event,closure)}else{this.element.undelegate(selector,event,closure)}delete this._closures[""+selector+"/"+event+"/"+functionName];return this};Delegator.prototype.publish=function(){this.element.triggerHandler.apply(this.element,arguments);return this};Delegator.prototype.subscribe=function(event,callback){var closure;closure=function(){return callback.apply(this,[].slice.call(arguments,1))};closure.guid=callback.guid=$.guid+=1;this.element.bind(event,closure);return this};Delegator.prototype.unsubscribe=function(){this.element.unbind.apply(this.element,arguments);return this};return Delegator}();Delegator._parseEvents=function(eventsObj){var event,events,functionName,sel,selector,_k,_ref1;events=[];for(sel in eventsObj){functionName=eventsObj[sel];_ref1=sel.split(" "),selector=2<=_ref1.length?__slice.call(_ref1,0,_k=_ref1.length-1):(_k=0,[]),event=_ref1[_k++];events.push({selector:selector.join(" "),event:event,functionName:functionName})}return events};Delegator.natives=function(){var key,specials,val;specials=function(){var _ref1,_results;_ref1=jQuery.event.special;_results=[];for(key in _ref1){if(!__hasProp.call(_ref1,key))continue;val=_ref1[key];_results.push(key)}return _results}();return"blur focus focusin focusout load resize scroll unload click dblclick\nmousedown mouseup mousemove mouseover mouseout mouseenter mouseleave\nchange select submit keydown keypress keyup error".split(/[^a-z]+/).concat(specials)}();Delegator._isCustomEvent=function(event){event=event.split(".")[0];return $.inArray(event,Delegator.natives)===-1};Range={};Range.sniff=function(r){if(r.commonAncestorContainer!=null){return new Range.BrowserRange(r)}else if(typeof r.start==="string"){return new Range.SerializedRange(r)}else if(r.start&&typeof r.start==="object"){return new Range.NormalizedRange(r)}else{console.error(_t("Could not sniff range type"));return false}};Range.nodeFromXPath=function(xpath,root){var customResolver,evaluateXPath,namespace,node,segment;if(root==null){root=document}evaluateXPath=function(xp,nsResolver){var exception;if(nsResolver==null){nsResolver=null}try{return document.evaluate("."+xp,root,nsResolver,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue}catch(_error){exception=_error;console.log("XPath evaluation failed.");console.log("Trying fallback...");return Util.nodeFromXPath(xp,root)}};if(!$.isXMLDoc(document.documentElement)){return evaluateXPath(xpath)}else{customResolver=document.createNSResolver(document.ownerDocument===null?document.documentElement:document.ownerDocument.documentElement);node=evaluateXPath(xpath,customResolver);if(!node){xpath=function(){var _k,_len2,_ref1,_results;_ref1=xpath.split("/");_results=[];for(_k=0,_len2=_ref1.length;_k<_len2;_k++){segment=_ref1[_k];if(segment&&segment.indexOf(":")===-1){_results.push(segment.replace(/^([a-z]+)/,"xhtml:$1"))}else{_results.push(segment)}}return _results}().join("/");namespace=document.lookupNamespaceURI(null);customResolver=function(ns){if(ns==="xhtml"){return namespace}else{return document.documentElement.getAttribute("xmlns:"+ns)}};node=evaluateXPath(xpath,customResolver)}return node}};Range.RangeError=function(_super){__extends(RangeError,_super);function RangeError(type,message,parent){this.type=type;this.message=message;this.parent=parent!=null?parent:null;RangeError.__super__.constructor.call(this,this.message)}return RangeError}(Error);Range.BrowserRange=function(){function BrowserRange(obj){this.commonAncestorContainer=obj.commonAncestorContainer;this.startContainer=obj.startContainer;this.startOffset=obj.startOffset;this.endContainer=obj.endContainer;this.endOffset=obj.endOffset}BrowserRange.prototype.normalize=function(root){var n,node,nr,r;if(this.tainted){console.error(_t("You may only call normalize() once on a BrowserRange!"));return false}else{this.tainted=true}r={};if(this.startContainer.nodeType===Node.ELEMENT_NODE){r.start=Util.getFirstTextNodeNotBefore(this.startContainer.childNodes[this.startOffset]);r.startOffset=0}else{r.start=this.startContainer;r.startOffset=this.startOffset}if(this.endContainer.nodeType===Node.ELEMENT_NODE){node=this.endContainer.childNodes[this.endOffset];if(node!=null){n=node;while(n!=null&&n.nodeType!==Node.TEXT_NODE){n=n.firstChild}if(n!=null){r.end=n;r.endOffset=0}}if(r.end==null){node=this.endContainer.childNodes[this.endOffset-1];r.end=Util.getLastTextNodeUpTo(node);r.endOffset=r.end.nodeValue.length}}else{r.end=this.endContainer;r.endOffset=this.endOffset}nr={};if(r.startOffset>0){if(r.start.nodeValue.length>r.startOffset){nr.start=r.start.splitText(r.startOffset)}else{nr.start=r.start.nextSibling}}else{nr.start=r.start}if(r.start===r.end){if(nr.start.nodeValue.length>r.endOffset-r.startOffset){nr.start.splitText(r.endOffset-r.startOffset)}nr.end=nr.start}else{if(r.end.nodeValue.length>r.endOffset){r.end.splitText(r.endOffset)}nr.end=r.end}nr.commonAncestor=this.commonAncestorContainer;while(nr.commonAncestor.nodeType!==Node.ELEMENT_NODE){nr.commonAncestor=nr.commonAncestor.parentNode}return new Range.NormalizedRange(nr)};BrowserRange.prototype.serialize=function(root,ignoreSelector){return this.normalize(root).serialize(root,ignoreSelector)};return BrowserRange}();Range.NormalizedRange=function(){function NormalizedRange(obj){this.commonAncestor=obj.commonAncestor;this.start=obj.start;this.end=obj.end}NormalizedRange.prototype.normalize=function(root){return this};NormalizedRange.prototype.limit=function(bounds){var nodes,parent,startParents,_k,_len2,_ref1;nodes=$.grep(this.textNodes(),function(node){return node.parentNode===bounds||$.contains(bounds,node.parentNode)});if(!nodes.length){return null}this.start=nodes[0];this.end=nodes[nodes.length-1];startParents=$(this.start).parents();_ref1=$(this.end).parents();for(_k=0,_len2=_ref1.length;_k<_len2;_k++){parent=_ref1[_k];if(startParents.index(parent)!==-1){this.commonAncestor=parent;break}}return this};NormalizedRange.prototype.serialize=function(root,ignoreSelector){var end,serialization,start;serialization=function(node,isEnd){var n,nodes,offset,origParent,textNodes,xpath,_k,_len2;if(ignoreSelector){origParent=$(node).parents(":not("+ignoreSelector+")").eq(0)}else{origParent=$(node).parent()}xpath=Util.xpathFromNode(origParent,root)[0];textNodes=Util.getTextNodes(origParent);nodes=textNodes.slice(0,textNodes.index(node));offset=0;for(_k=0,_len2=nodes.length;_k<_len2;_k++){n=nodes[_k];offset+=n.nodeValue.length}if(isEnd){return[xpath,offset+node.nodeValue.length]}else{return[xpath,offset]}};start=serialization(this.start);end=serialization(this.end,true);return new Range.SerializedRange({start:start[0],end:end[0],startOffset:start[1],endOffset:end[1]})};NormalizedRange.prototype.text=function(){var node;return function(){var _k,_len2,_ref1,_results;_ref1=this.textNodes();_results=[];for(_k=0,_len2=_ref1.length;_k<_len2;_k++){node=_ref1[_k];_results.push(node.nodeValue)}return _results}.call(this).join("")};NormalizedRange.prototype.textNodes=function(){var end,start,textNodes,_ref1;textNodes=Util.getTextNodes($(this.commonAncestor));_ref1=[textNodes.index(this.start),textNodes.index(this.end)],start=_ref1[0],end=_ref1[1];return $.makeArray(textNodes.slice(start,+end+1||9e9))};NormalizedRange.prototype.toRange=function(){var range;range=document.createRange();range.setStartBefore(this.start);range.setEndAfter(this.end);return range};return NormalizedRange}();Range.SerializedRange=function(){function SerializedRange(obj){this.start=obj.start;this.startOffset=obj.startOffset;this.end=obj.end;this.endOffset=obj.endOffset}SerializedRange.prototype.normalize=function(root){var contains,e,length,node,p,range,targetOffset,tn,_k,_l,_len2,_len3,_ref1,_ref2;range={};_ref1=["start","end"];for(_k=0,_len2=_ref1.length;_k<_len2;_k++){p=_ref1[_k];try{node=Range.nodeFromXPath(this[p],root)}catch(_error){e=_error;throw new Range.RangeError(p,"Error while finding "+p+" node: "+this[p]+": "+e,e)}if(!node){throw new Range.RangeError(p,"Couldn't find "+p+" node: "+this[p])}length=0;targetOffset=this[p+"Offset"];if(p==="end"){targetOffset--}_ref2=Util.getTextNodes($(node));for(_l=0,_len3=_ref2.length;_l<_len3;_l++){tn=_ref2[_l];if(length+tn.nodeValue.length>targetOffset){range[p+"Container"]=tn;range[p+"Offset"]=this[p+"Offset"]-length;break}else{length+=tn.nodeValue.length}}if(range[p+"Offset"]==null){throw new Range.RangeError(""+p+"offset","Couldn't find offset "+this[p+"Offset"]+" in element "+this[p])}}contains=document.compareDocumentPosition==null?function(a,b){return a.contains(b)}:function(a,b){return a.compareDocumentPosition(b)&16};$(range.startContainer).parents().each(function(){if(contains(this,range.endContainer)){range.commonAncestorContainer=this;return false}});return new Range.BrowserRange(range).normalize(root)};SerializedRange.prototype.serialize=function(root,ignoreSelector){return this.normalize(root).serialize(root,ignoreSelector)};SerializedRange.prototype.toObject=function(){return{start:this.start,startOffset:this.startOffset,end:this.end,endOffset:this.endOffset}};return SerializedRange}();_Annotator=this.Annotator;Annotator=function(_super){__extends(Annotator,_super);Annotator.prototype.events={".annotator-adder button click":"onAdderClick",".annotator-adder button mousedown":"onAdderMousedown",".annotator-hl mouseover":"onHighlightMouseover",".annotator-hl mouseout":"startViewerHideTimer"};Annotator.prototype.html={adder:'<div class="annotator-adder"><button>'+_t("Annotate")+"</button></div>",wrapper:'<div class="annotator-wrapper"></div>'};Annotator.prototype.options={readOnly:false};Annotator.prototype.plugins={};Annotator.prototype.editor=null;Annotator.prototype.viewer=null;Annotator.prototype.selectedRanges=null;Annotator.prototype.mouseIsDown=false;Annotator.prototype.ignoreMouseup=false;Annotator.prototype.viewerHideTimer=null;function Annotator(element,options){this.onDeleteAnnotation=__bind(this.onDeleteAnnotation,this);this.onEditAnnotation=__bind(this.onEditAnnotation,this);this.onAdderClick=__bind(this.onAdderClick,this);this.onAdderMousedown=__bind(this.onAdderMousedown,this);this.onHighlightMouseover=__bind(this.onHighlightMouseover,this);this.checkForEndSelection=__bind(this.checkForEndSelection,this);this.checkForStartSelection=__bind(this.checkForStartSelection,this);this.clearViewerHideTimer=__bind(this.clearViewerHideTimer,this);this.startViewerHideTimer=__bind(this.startViewerHideTimer,this);this.showViewer=__bind(this.showViewer,this);this.onEditorSubmit=__bind(this.onEditorSubmit,this);this.onEditorHide=__bind(this.onEditorHide,this);this.showEditor=__bind(this.showEditor,this);Annotator.__super__.constructor.apply(this,arguments);this.plugins={};if(!Annotator.supported()){return this}if(!this.options.readOnly){this._setupDocumentEvents()}this._setupWrapper()._setupViewer()._setupEditor();this._setupDynamicStyle();this.adder=$(this.html.adder).appendTo(this.wrapper).hide();Annotator._instances.push(this)}Annotator.prototype._setupWrapper=function(){this.wrapper=$(this.html.wrapper);this.element.find("script").remove();this.element.wrapInner(this.wrapper);this.wrapper=this.element.find(".annotator-wrapper");return this};Annotator.prototype._setupViewer=function(){this.viewer=new Annotator.Viewer({readOnly:this.options.readOnly});this.viewer.hide().on("edit",this.onEditAnnotation).on("delete",this.onDeleteAnnotation).addField({load:function(_this){return function(field,annotation){if(annotation.text){$(field).html(Util.escape(annotation.text))}else{$(field).html("<i>"+_t("No Comment")+"</i>")}return _this.publish("annotationViewerTextField",[field,annotation])}}(this)}).element.appendTo(this.wrapper).bind({mouseover:this.clearViewerHideTimer,mouseout:this.startViewerHideTimer});return this};Annotator.prototype._setupEditor=function(){this.editor=new Annotator.Editor;this.editor.hide().on("hide",this.onEditorHide).on("save",this.onEditorSubmit).addField({type:"textarea",label:_t("Comments")+"…",load:function(field,annotation){return $(field).find("textarea").val(annotation.text||"")},submit:function(field,annotation){return annotation.text=$(field).find("textarea").val()}});this.editor.element.appendTo(this.wrapper);return this};Annotator.prototype._setupDocumentEvents=function(){$(document).bind({mouseup:this.checkForEndSelection,mousedown:this.checkForStartSelection});return this};Annotator.prototype._setupDynamicStyle=function(){var max,sel,style,x;style=$("#annotator-dynamic-style");if(!style.length){style=$('<style id="annotator-dynamic-style"></style>').appendTo(document.head)}sel="*"+function(){var _k,_len2,_ref1,_results;_ref1=["adder","outer","notice","filter"];_results=[];for(_k=0,_len2=_ref1.length;_k<_len2;_k++){x=_ref1[_k];_results.push(":not(.annotator-"+x+")")}return _results}().join("");max=Util.maxZIndex($(document.body).find(sel));max=Math.max(max,1e3);style.text([".annotator-adder, .annotator-outer, .annotator-notice {","  z-index: "+(max+20)+";","}",".annotator-filter {","  z-index: "+(max+10)+";","}"].join("\n"));return this};Annotator.prototype.destroy=function(){var idx,name,plugin,_ref1;$(document).unbind({mouseup:this.checkForEndSelection,mousedown:this.checkForStartSelection});$("#annotator-dynamic-style").remove();this.adder.remove();this.viewer.destroy();this.editor.destroy();this.wrapper.find(".annotator-hl").each(function(){$(this).contents().insertBefore(this);return $(this).remove()});this.wrapper.contents().insertBefore(this.wrapper);this.wrapper.remove();this.element.data("annotator",null);_ref1=this.plugins;for(name in _ref1){plugin=_ref1[name];this.plugins[name].destroy()}this.removeEvents();idx=Annotator._instances.indexOf(this);if(idx!==-1){return Annotator._instances.splice(idx,1)}};Annotator.prototype.getSelectedRanges=function(){var browserRange,i,normedRange,r,ranges,rangesToIgnore,selection,_k,_len2;selection=Util.getGlobal().getSelection();ranges=[];rangesToIgnore=[];if(!selection.isCollapsed){ranges=function(){var _k,_ref1,_results;_results=[];for(i=_k=0,_ref1=selection.rangeCount;0<=_ref1?_k<_ref1:_k>_ref1;i=0<=_ref1?++_k:--_k){r=selection.getRangeAt(i);browserRange=new Range.BrowserRange(r);normedRange=browserRange.normalize().limit(this.wrapper[0]);if(normedRange===null){rangesToIgnore.push(r)}_results.push(normedRange)}return _results}.call(this);selection.removeAllRanges()}for(_k=0,_len2=rangesToIgnore.length;_k<_len2;_k++){r=rangesToIgnore[_k];selection.addRange(r)}return $.grep(ranges,function(range){if(range){selection.addRange(range.toRange())}return range})};Annotator.prototype.createAnnotation=function(){var annotation;annotation={};this.publish("beforeAnnotationCreated",[annotation]);return annotation};Annotator.prototype.setupAnnotation=function(annotation){var e,normed,normedRanges,r,root,_k,_l,_len2,_len3,_ref1;root=this.wrapper[0];annotation.ranges||(annotation.ranges=this.selectedRanges);normedRanges=[];_ref1=annotation.ranges;for(_k=0,_len2=_ref1.length;_k<_len2;_k++){r=_ref1[_k];try{normedRanges.push(Range.sniff(r).normalize(root))}catch(_error){e=_error;if(e instanceof Range.RangeError){this.publish("rangeNormalizeFail",[annotation,r,e])}else{throw e}}}annotation.quote=[];annotation.ranges=[];annotation.highlights=[];for(_l=0,_len3=normedRanges.length;_l<_len3;_l++){normed=normedRanges[_l];annotation.quote.push($.trim(normed.text()));annotation.ranges.push(normed.serialize(this.wrapper[0],".annotator-hl"));$.merge(annotation.highlights,this.highlightRange(normed))}annotation.quote=annotation.quote.join(" / ");$(annotation.highlights).data("annotation",annotation);return annotation};Annotator.prototype.updateAnnotation=function(annotation){this.publish("beforeAnnotationUpdated",[annotation]);this.publish("annotationUpdated",[annotation]);return annotation};Annotator.prototype.deleteAnnotation=function(annotation){var child,h,_k,_len2,_ref1;if(annotation.highlights!=null){_ref1=annotation.highlights;for(_k=0,_len2=_ref1.length;_k<_len2;_k++){h=_ref1[_k];if(!(h.parentNode!=null)){continue}child=h.childNodes[0];$(h).replaceWith(h.childNodes)}}this.publish("annotationDeleted",[annotation]);return annotation};Annotator.prototype.loadAnnotations=function(annotations){var clone,loader;if(annotations==null){annotations=[]}loader=function(_this){return function(annList){var n,now,_k,_len2;if(annList==null){annList=[]}now=annList.splice(0,10);for(_k=0,_len2=now.length;_k<_len2;_k++){n=now[_k];_this.setupAnnotation(n)}if(annList.length>0){return setTimeout(function(){return loader(annList)},10)}else{return _this.publish("annotationsLoaded",[clone])}}}(this);clone=annotations.slice();loader(annotations);return this};Annotator.prototype.dumpAnnotations=function(){if(this.plugins["Store"]){return this.plugins["Store"].dumpAnnotations()}else{console.warn(_t("Can't dump annotations without Store plugin."));return false}};Annotator.prototype.highlightRange=function(normedRange,cssClass){var hl,node,white,_k,_len2,_ref1,_results;if(cssClass==null){cssClass="annotator-hl"}white=/^\s*$/;hl=$("<span class='"+cssClass+"'></span>");_ref1=normedRange.textNodes();_results=[];for(_k=0,_len2=_ref1.length;_k<_len2;_k++){node=_ref1[_k];if(!white.test(node.nodeValue)){_results.push($(node).wrapAll(hl).parent().show()[0])}}return _results};Annotator.prototype.highlightRanges=function(normedRanges,cssClass){var highlights,r,_k,_len2;if(cssClass==null){cssClass="annotator-hl"}highlights=[];for(_k=0,_len2=normedRanges.length;_k<_len2;_k++){r=normedRanges[_k];$.merge(highlights,this.highlightRange(r,cssClass))}return highlights};Annotator.prototype.addPlugin=function(name,options){var klass,_base;if(this.plugins[name]){console.error(_t("You cannot have more than one instance of any plugin."))}else{klass=Annotator.Plugin[name];if(typeof klass==="function"){this.plugins[name]=new klass(this.element[0],options);this.plugins[name].annotator=this;if(typeof(_base=this.plugins[name]).pluginInit==="function"){_base.pluginInit()}}else{console.error(_t("Could not load ")+name+_t(" plugin. Have you included the appropriate <script> tag?"))}}return this};Annotator.prototype.showEditor=function(annotation,location){this.editor.element.css(location);this.editor.load(annotation);this.publish("annotationEditorShown",[this.editor,annotation]);return this};Annotator.prototype.onEditorHide=function(){this.publish("annotationEditorHidden",[this.editor]);return this.ignoreMouseup=false};Annotator.prototype.onEditorSubmit=function(annotation){return this.publish("annotationEditorSubmit",[this.editor,annotation])};Annotator.prototype.showViewer=function(annotations,location){this.viewer.element.css(location);this.viewer.load(annotations);return this.publish("annotationViewerShown",[this.viewer,annotations])};Annotator.prototype.startViewerHideTimer=function(){if(!this.viewerHideTimer){return this.viewerHideTimer=setTimeout(this.viewer.hide,250)}};Annotator.prototype.clearViewerHideTimer=function(){clearTimeout(this.viewerHideTimer);return this.viewerHideTimer=false};Annotator.prototype.checkForStartSelection=function(event){if(!(event&&this.isAnnotator(event.target))){this.startViewerHideTimer()}return this.mouseIsDown=true};Annotator.prototype.checkForEndSelection=function(event){var container,range,_k,_len2,_ref1;this.mouseIsDown=false;if(this.ignoreMouseup){return}this.selectedRanges=this.getSelectedRanges();_ref1=this.selectedRanges;for(_k=0,_len2=_ref1.length;_k<_len2;_k++){range=_ref1[_k];container=range.commonAncestor;if($(container).hasClass("annotator-hl")){container=$(container).parents("[class!=annotator-hl]")[0]}if(this.isAnnotator(container)){return}}if(event&&this.selectedRanges.length){return this.adder.css(Util.mousePosition(event,this.wrapper[0])).show()}else{return this.adder.hide()}};Annotator.prototype.isAnnotator=function(element){return!!$(element).parents().addBack().filter("[class^=annotator-]").not(this.wrapper).length};Annotator.prototype.onHighlightMouseover=function(event){var annotations;this.clearViewerHideTimer();if(this.mouseIsDown||this.viewer.isShown()){return false}annotations=$(event.target).parents(".annotator-hl").addBack().map(function(){return $(this).data("annotation")});return this.showViewer($.makeArray(annotations),Util.mousePosition(event,this.wrapper[0]))};Annotator.prototype.onAdderMousedown=function(event){if(event!=null){event.preventDefault()}return this.ignoreMouseup=true};Annotator.prototype.onAdderClick=function(event){var annotation,cancel,cleanup,position,save;if(event!=null){event.preventDefault()}position=this.adder.position();this.adder.hide();annotation=this.setupAnnotation(this.createAnnotation());$(annotation.highlights).addClass("annotator-hl-temporary");save=function(_this){return function(){cleanup();$(annotation.highlights).removeClass("annotator-hl-temporary");return _this.publish("annotationCreated",[annotation])}}(this);cancel=function(_this){return function(){cleanup();return _this.deleteAnnotation(annotation)}}(this);cleanup=function(_this){return function(){_this.unsubscribe("annotationEditorHidden",cancel);return _this.unsubscribe("annotationEditorSubmit",save)}}(this);this.subscribe("annotationEditorHidden",cancel);this.subscribe("annotationEditorSubmit",save);return this.showEditor(annotation,position)};Annotator.prototype.onEditAnnotation=function(annotation){var cleanup,offset,update;offset=this.viewer.element.position();update=function(_this){return function(){cleanup();return _this.updateAnnotation(annotation)}}(this);cleanup=function(_this){return function(){_this.unsubscribe("annotationEditorHidden",cleanup);return _this.unsubscribe("annotationEditorSubmit",update)}}(this);this.subscribe("annotationEditorHidden",cleanup);this.subscribe("annotationEditorSubmit",update);this.viewer.hide();return this.showEditor(annotation,offset)};Annotator.prototype.onDeleteAnnotation=function(annotation){this.viewer.hide();return this.deleteAnnotation(annotation)};return Annotator}(Delegator);Annotator.Plugin=function(_super){__extends(Plugin,_super);function Plugin(element,options){Plugin.__super__.constructor.apply(this,arguments)}Plugin.prototype.pluginInit=function(){};Plugin.prototype.destroy=function(){return this.removeEvents()};return Plugin}(Delegator);g=Util.getGlobal();if(((_ref1=g.document)!=null?_ref1.evaluate:void 0)==null){$.getScript("http://assets.annotateit.org/vendor/xpath.min.js")}if(g.getSelection==null){$.getScript("http://assets.annotateit.org/vendor/ierange.min.js")}if(g.JSON==null){$.getScript("http://assets.annotateit.org/vendor/json2.min.js")}if(g.Node==null){g.Node={ELEMENT_NODE:1,ATTRIBUTE_NODE:2,TEXT_NODE:3,CDATA_SECTION_NODE:4,ENTITY_REFERENCE_NODE:5,ENTITY_NODE:6,PROCESSING_INSTRUCTION_NODE:7,COMMENT_NODE:8,DOCUMENT_NODE:9,DOCUMENT_TYPE_NODE:10,DOCUMENT_FRAGMENT_NODE:11,NOTATION_NODE:12}}Annotator.$=$;Annotator.Delegator=Delegator;Annotator.Range=Range;Annotator.Util=Util;Annotator._instances=[];Annotator._t=_t;Annotator.supported=function(){return function(){return!!this.getSelection}()};Annotator.noConflict=function(){Util.getGlobal().Annotator=_Annotator;return this};$.fn.annotator=function(options){var args;args=Array.prototype.slice.call(arguments,1);return this.each(function(){var instance;instance=$.data(this,"annotator");if(instance){return options&&instance[options].apply(instance,args)
+}else{instance=new Annotator(this,options);return $.data(this,"annotator",instance)}})};this.Annotator=Annotator;Annotator.Widget=function(_super){__extends(Widget,_super);Widget.prototype.classes={hide:"annotator-hide",invert:{x:"annotator-invert-x",y:"annotator-invert-y"}};function Widget(element,options){Widget.__super__.constructor.apply(this,arguments);this.classes=$.extend({},Annotator.Widget.prototype.classes,this.classes)}Widget.prototype.destroy=function(){this.removeEvents();return this.element.remove()};Widget.prototype.checkOrientation=function(){var current,offset,viewport,widget,window;this.resetOrientation();window=$(Annotator.Util.getGlobal());widget=this.element.children(":first");offset=widget.offset();viewport={top:window.scrollTop(),right:window.width()+window.scrollLeft()};current={top:offset.top,right:offset.left+widget.width()};if(current.top-viewport.top<0){this.invertY()}if(current.right-viewport.right>0){this.invertX()}return this};Widget.prototype.resetOrientation=function(){this.element.removeClass(this.classes.invert.x).removeClass(this.classes.invert.y);return this};Widget.prototype.invertX=function(){this.element.addClass(this.classes.invert.x);return this};Widget.prototype.invertY=function(){this.element.addClass(this.classes.invert.y);return this};Widget.prototype.isInvertedY=function(){return this.element.hasClass(this.classes.invert.y)};Widget.prototype.isInvertedX=function(){return this.element.hasClass(this.classes.invert.x)};return Widget}(Delegator);Annotator.Editor=function(_super){__extends(Editor,_super);Editor.prototype.events={"form submit":"submit",".annotator-save click":"submit",".annotator-cancel click":"hide",".annotator-cancel mouseover":"onCancelButtonMouseover","textarea keydown":"processKeypress"};Editor.prototype.classes={hide:"annotator-hide",focus:"annotator-focus"};Editor.prototype.html='<div class="annotator-outer annotator-editor">\n  <form class="annotator-widget">\n    <ul class="annotator-listing"></ul>\n    <div class="annotator-controls">\n      <a href="#cancel" class="annotator-cancel">'+_t("Cancel")+'</a>\n<a href="#save" class="annotator-save annotator-focus">'+_t("Save")+"</a>\n    </div>\n  </form>\n</div>";Editor.prototype.options={};function Editor(options){this.onCancelButtonMouseover=__bind(this.onCancelButtonMouseover,this);this.processKeypress=__bind(this.processKeypress,this);this.submit=__bind(this.submit,this);this.load=__bind(this.load,this);this.hide=__bind(this.hide,this);this.show=__bind(this.show,this);Editor.__super__.constructor.call(this,$(this.html)[0],options);this.fields=[];this.annotation={}}Editor.prototype.show=function(event){Annotator.Util.preventEventDefault(event);this.element.removeClass(this.classes.hide);this.element.find(".annotator-save").addClass(this.classes.focus);this.checkOrientation();this.element.find(":input:first").focus();this.setupDraggables();return this.publish("show")};Editor.prototype.hide=function(event){Annotator.Util.preventEventDefault(event);this.element.addClass(this.classes.hide);return this.publish("hide")};Editor.prototype.load=function(annotation){var field,_k,_len2,_ref2;this.annotation=annotation;this.publish("load",[this.annotation]);_ref2=this.fields;for(_k=0,_len2=_ref2.length;_k<_len2;_k++){field=_ref2[_k];field.load(field.element,this.annotation)}return this.show()};Editor.prototype.submit=function(event){var field,_k,_len2,_ref2;Annotator.Util.preventEventDefault(event);_ref2=this.fields;for(_k=0,_len2=_ref2.length;_k<_len2;_k++){field=_ref2[_k];field.submit(field.element,this.annotation)}this.publish("save",[this.annotation]);return this.hide()};Editor.prototype.addField=function(options){var element,field,input;field=$.extend({id:"annotator-field-"+Annotator.Util.uuid(),type:"input",label:"",load:function(){},submit:function(){}},options);input=null;element=$('<li class="annotator-item" />');field.element=element[0];switch(field.type){case"textarea":input=$("<textarea />");break;case"input":case"checkbox":input=$("<input />");break;case"select":input=$("<select />")}element.append(input);input.attr({id:field.id,placeholder:field.label});if(field.type==="checkbox"){input[0].type="checkbox";element.addClass("annotator-checkbox");element.append($("<label />",{"for":field.id,html:field.label}))}this.element.find("ul:first").append(element);this.fields.push(field);return field.element};Editor.prototype.checkOrientation=function(){var controls,list;Editor.__super__.checkOrientation.apply(this,arguments);list=this.element.find("ul");controls=this.element.find(".annotator-controls");if(this.element.hasClass(this.classes.invert.y)){controls.insertBefore(list)}else if(controls.is(":first-child")){controls.insertAfter(list)}return this};Editor.prototype.processKeypress=function(event){if(event.keyCode===27){return this.hide()}else if(event.keyCode===13&&!event.shiftKey){return this.submit()}};Editor.prototype.onCancelButtonMouseover=function(){return this.element.find("."+this.classes.focus).removeClass(this.classes.focus)};Editor.prototype.setupDraggables=function(){var classes,controls,cornerItem,editor,mousedown,onMousedown,onMousemove,onMouseup,resize,textarea,throttle;this.element.find(".annotator-resize").remove();if(this.element.hasClass(this.classes.invert.y)){cornerItem=this.element.find(".annotator-item:last")}else{cornerItem=this.element.find(".annotator-item:first")}if(cornerItem){$('<span class="annotator-resize"></span>').appendTo(cornerItem)}mousedown=null;classes=this.classes;editor=this.element;textarea=null;resize=editor.find(".annotator-resize");controls=editor.find(".annotator-controls");throttle=false;onMousedown=function(event){if(event.target===this){mousedown={element:this,top:event.pageY,left:event.pageX};textarea=editor.find("textarea:first");$(window).bind({"mouseup.annotator-editor-resize":onMouseup,"mousemove.annotator-editor-resize":onMousemove});return event.preventDefault()}};onMouseup=function(){mousedown=null;return $(window).unbind(".annotator-editor-resize")};onMousemove=function(_this){return function(event){var diff,directionX,directionY,height,width;if(mousedown&&throttle===false){diff={top:event.pageY-mousedown.top,left:event.pageX-mousedown.left};if(mousedown.element===resize[0]){height=textarea.outerHeight();width=textarea.outerWidth();directionX=editor.hasClass(classes.invert.x)?-1:1;directionY=editor.hasClass(classes.invert.y)?1:-1;textarea.height(height+diff.top*directionY);textarea.width(width+diff.left*directionX);if(textarea.outerHeight()!==height){mousedown.top=event.pageY}if(textarea.outerWidth()!==width){mousedown.left=event.pageX}}else if(mousedown.element===controls[0]){editor.css({top:parseInt(editor.css("top"),10)+diff.top,left:parseInt(editor.css("left"),10)+diff.left});mousedown.top=event.pageY;mousedown.left=event.pageX}throttle=true;return setTimeout(function(){return throttle=false},1e3/60)}}}(this);resize.bind("mousedown",onMousedown);return controls.bind("mousedown",onMousedown)};return Editor}(Annotator.Widget);Annotator.Viewer=function(_super){__extends(Viewer,_super);Viewer.prototype.events={".annotator-edit click":"onEditClick",".annotator-delete click":"onDeleteClick"};Viewer.prototype.classes={hide:"annotator-hide",showControls:"annotator-visible"};Viewer.prototype.html={element:'<div class="annotator-outer annotator-viewer">\n  <ul class="annotator-widget annotator-listing"></ul>\n</div>',item:'<li class="annotator-annotation annotator-item">\n  <span class="annotator-controls">\n    <a href="#" title="View as webpage" class="annotator-link">View as webpage</a>\n    <button title="Edit" class="annotator-edit">Edit</button>\n    <button title="Delete" class="annotator-delete">Delete</button>\n  </span>\n</li>'};Viewer.prototype.options={readOnly:false};function Viewer(options){this.onDeleteClick=__bind(this.onDeleteClick,this);this.onEditClick=__bind(this.onEditClick,this);this.load=__bind(this.load,this);this.hide=__bind(this.hide,this);this.show=__bind(this.show,this);Viewer.__super__.constructor.call(this,$(this.html.element)[0],options);this.item=$(this.html.item)[0];this.fields=[];this.annotations=[]}Viewer.prototype.show=function(event){var controls;Annotator.Util.preventEventDefault(event);controls=this.element.find(".annotator-controls").addClass(this.classes.showControls);setTimeout(function(_this){return function(){return controls.removeClass(_this.classes.showControls)}}(this),500);this.element.removeClass(this.classes.hide);return this.checkOrientation().publish("show")};Viewer.prototype.isShown=function(){return!this.element.hasClass(this.classes.hide)};Viewer.prototype.hide=function(event){Annotator.Util.preventEventDefault(event);this.element.addClass(this.classes.hide);return this.publish("hide")};Viewer.prototype.load=function(annotations){var annotation,controller,controls,del,edit,element,field,item,link,links,list,_k,_l,_len2,_len3,_ref2,_ref3;this.annotations=annotations||[];list=this.element.find("ul:first").empty();_ref2=this.annotations;for(_k=0,_len2=_ref2.length;_k<_len2;_k++){annotation=_ref2[_k];item=$(this.item).clone().appendTo(list).data("annotation",annotation);controls=item.find(".annotator-controls");link=controls.find(".annotator-link");edit=controls.find(".annotator-edit");del=controls.find(".annotator-delete");links=new LinkParser(annotation.links||[]).get("alternate",{type:"text/html"});if(links.length===0||links[0].href==null){link.remove()}else{link.attr("href",links[0].href)}if(this.options.readOnly){edit.remove();del.remove()}else{controller={showEdit:function(){return edit.removeAttr("disabled")},hideEdit:function(){return edit.attr("disabled","disabled")},showDelete:function(){return del.removeAttr("disabled")},hideDelete:function(){return del.attr("disabled","disabled")}}}_ref3=this.fields;for(_l=0,_len3=_ref3.length;_l<_len3;_l++){field=_ref3[_l];element=$(field.element).clone().appendTo(item)[0];field.load(element,annotation,controller)}}this.publish("load",[this.annotations]);return this.show()};Viewer.prototype.addField=function(options){var field;field=$.extend({load:function(){}},options);field.element=$("<div />")[0];this.fields.push(field);field.element;return this};Viewer.prototype.onEditClick=function(event){return this.onButtonClick(event,"edit")};Viewer.prototype.onDeleteClick=function(event){return this.onButtonClick(event,"delete")};Viewer.prototype.onButtonClick=function(event,type){var item;item=$(event.target).parents(".annotator-annotation");return this.publish(type,[item.data("annotation")])};return Viewer}(Annotator.Widget);LinkParser=function(){function LinkParser(data){this.data=data}LinkParser.prototype.get=function(rel,cond){var d,k,keys,match,v,_k,_len2,_ref2,_results;if(cond==null){cond={}}cond=$.extend({},cond,{rel:rel});keys=function(){var _results;_results=[];for(k in cond){if(!__hasProp.call(cond,k))continue;v=cond[k];_results.push(k)}return _results}();_ref2=this.data;_results=[];for(_k=0,_len2=_ref2.length;_k<_len2;_k++){d=_ref2[_k];match=keys.reduce(function(m,k){return m&&d[k]===cond[k]},true);if(match){_results.push(d)}else{continue}}return _results};return LinkParser}();Annotator=Annotator||{};Annotator.Notification=function(_super){__extends(Notification,_super);Notification.prototype.events={click:"hide"};Notification.prototype.options={html:"<div class='annotator-notice'></div>",classes:{show:"annotator-notice-show",info:"annotator-notice-info",success:"annotator-notice-success",error:"annotator-notice-error"}};function Notification(options){this.hide=__bind(this.hide,this);this.show=__bind(this.show,this);Notification.__super__.constructor.call(this,$(this.options.html).appendTo(document.body)[0],options)}Notification.prototype.show=function(message,status){if(status==null){status=Annotator.Notification.INFO}this.currentStatus=status;$(this.element).addClass(this.options.classes.show).addClass(this.options.classes[this.currentStatus]).html(Util.escape(message||""));setTimeout(this.hide,5e3);return this};Notification.prototype.hide=function(){if(this.currentStatus==null){this.currentStatus=Annotator.Notification.INFO}$(this.element).removeClass(this.options.classes.show).removeClass(this.options.classes[this.currentStatus]);return this};return Notification}(Delegator);Annotator.Notification.INFO="info";Annotator.Notification.SUCCESS="success";Annotator.Notification.ERROR="error";$(function(){var notification;notification=new Annotator.Notification;Annotator.showNotification=notification.show;return Annotator.hideNotification=notification.hide});Annotator.Plugin.Unsupported=function(_super){__extends(Unsupported,_super);function Unsupported(){return Unsupported.__super__.constructor.apply(this,arguments)}Unsupported.prototype.options={message:Annotator._t("Sorry your current browser does not support the Annotator")};Unsupported.prototype.pluginInit=function(){if(!Annotator.supported()){return $(function(_this){return function(){Annotator.showNotification(_this.options.message);if(window.XMLHttpRequest===void 0&&ActiveXObject!==void 0){return $("html").addClass("ie6")}}}(this))}};return Unsupported}(Annotator.Plugin);createDateFromISO8601=function(string){var d,date,offset,regexp,time,_ref2;regexp="([0-9]{4})(-([0-9]{2})(-([0-9]{2})"+"(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\\.([0-9]+))?)?"+"(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";d=string.match(new RegExp(regexp));offset=0;date=new Date(d[1],0,1);if(d[3]){date.setMonth(d[3]-1)}if(d[5]){date.setDate(d[5])}if(d[7]){date.setHours(d[7])}if(d[8]){date.setMinutes(d[8])}if(d[10]){date.setSeconds(d[10])}if(d[12]){date.setMilliseconds(Number("0."+d[12])*1e3)}if(d[14]){offset=Number(d[16])*60+Number(d[17]);offset*=(_ref2=d[15]==="-")!=null?_ref2:{1:-1}}offset-=date.getTimezoneOffset();time=Number(date)+offset*60*1e3;date.setTime(Number(time));return date};base64Decode=function(data){var ac,b64,bits,dec,h1,h2,h3,h4,i,o1,o2,o3,tmp_arr;if(typeof atob!=="undefined"&&atob!==null){return atob(data)}else{b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";i=0;ac=0;dec="";tmp_arr=[];if(!data){return data}data+="";while(i<data.length){h1=b64.indexOf(data.charAt(i++));h2=b64.indexOf(data.charAt(i++));h3=b64.indexOf(data.charAt(i++));h4=b64.indexOf(data.charAt(i++));bits=h1<<18|h2<<12|h3<<6|h4;o1=bits>>16&255;o2=bits>>8&255;o3=bits&255;if(h3===64){tmp_arr[ac++]=String.fromCharCode(o1)}else if(h4===64){tmp_arr[ac++]=String.fromCharCode(o1,o2)}else{tmp_arr[ac++]=String.fromCharCode(o1,o2,o3)}}return tmp_arr.join("")}};base64UrlDecode=function(data){var i,m,_k,_ref2;m=data.length%4;if(m!==0){for(i=_k=0,_ref2=4-m;0<=_ref2?_k<_ref2:_k>_ref2;i=0<=_ref2?++_k:--_k){data+="="}}data=data.replace(/-/g,"+");data=data.replace(/_/g,"/");return base64Decode(data)};parseToken=function(token){var head,payload,sig,_ref2;_ref2=token.split("."),head=_ref2[0],payload=_ref2[1],sig=_ref2[2];return JSON.parse(base64UrlDecode(payload))};Annotator.Plugin.Auth=function(_super){__extends(Auth,_super);Auth.prototype.options={token:null,tokenUrl:"/auth/token",autoFetch:true};function Auth(element,options){Auth.__super__.constructor.apply(this,arguments);this.waitingForToken=[];if(this.options.token){this.setToken(this.options.token)}else{this.requestToken()}}Auth.prototype.requestToken=function(){this.requestInProgress=true;return $.ajax({url:this.options.tokenUrl,dataType:"text",xhrFields:{withCredentials:true}}).done(function(_this){return function(data,status,xhr){return _this.setToken(data)}}(this)).fail(function(_this){return function(xhr,status,err){var msg;msg=Annotator._t("Couldn't get auth token:");console.error(""+msg+" "+err,xhr);return Annotator.showNotification(""+msg+" "+xhr.responseText,Annotator.Notification.ERROR)}}(this)).always(function(_this){return function(){return _this.requestInProgress=false}}(this))};Auth.prototype.setToken=function(token){var _results;this.token=token;this._unsafeToken=parseToken(token);if(this.haveValidToken()){if(this.options.autoFetch){this.refreshTimeout=setTimeout(function(_this){return function(){return _this.requestToken()}}(this),(this.timeToExpiry()-2)*1e3)}this.updateHeaders();_results=[];while(this.waitingForToken.length>0){_results.push(this.waitingForToken.pop()(this._unsafeToken))}return _results}else{console.warn(Annotator._t("Didn't get a valid token."));if(this.options.autoFetch){console.warn(Annotator._t("Getting a new token in 10s."));return setTimeout(function(_this){return function(){return _this.requestToken()}}(this),10*1e3)}}};Auth.prototype.haveValidToken=function(){var allFields;allFields=this._unsafeToken&&this._unsafeToken.issuedAt&&this._unsafeToken.ttl&&this._unsafeToken.consumerKey;if(allFields&&this.timeToExpiry()>0){return true}else{return false}};Auth.prototype.timeToExpiry=function(){var expiry,issue,now,timeToExpiry;now=(new Date).getTime()/1e3;issue=createDateFromISO8601(this._unsafeToken.issuedAt).getTime()/1e3;expiry=issue+this._unsafeToken.ttl;timeToExpiry=expiry-now;if(timeToExpiry>0){return timeToExpiry}else{return 0}};Auth.prototype.updateHeaders=function(){var current;current=this.element.data("annotator:headers");return this.element.data("annotator:headers",$.extend(current,{"x-annotator-auth-token":this.token}))};Auth.prototype.withToken=function(callback){if(callback==null){return}if(this.haveValidToken()){return callback(this._unsafeToken)}else{this.waitingForToken.push(callback);if(!this.requestInProgress){return this.requestToken()}}};return Auth}(Annotator.Plugin);Annotator.Plugin.Store=function(_super){__extends(Store,_super);Store.prototype.events={annotationCreated:"annotationCreated",annotationDeleted:"annotationDeleted",annotationUpdated:"annotationUpdated"};Store.prototype.options={annotationData:{},emulateHTTP:false,loadFromSearch:false,prefix:"/store",urls:{create:"/annotations",read:"/annotations/:id",update:"/annotations/:id",destroy:"/annotations/:id",search:"/search"}};function Store(element,options){this._onError=__bind(this._onError,this);this._onLoadAnnotationsFromSearch=__bind(this._onLoadAnnotationsFromSearch,this);this._onLoadAnnotations=__bind(this._onLoadAnnotations,this);this._getAnnotations=__bind(this._getAnnotations,this);Store.__super__.constructor.apply(this,arguments);this.annotations=[]}Store.prototype.pluginInit=function(){if(!Annotator.supported()){return}if(this.annotator.plugins.Auth){return this.annotator.plugins.Auth.withToken(this._getAnnotations)}else{return this._getAnnotations()}};Store.prototype._getAnnotations=function(){if(this.options.loadFromSearch){return this.loadAnnotationsFromSearch(this.options.loadFromSearch)}else{return this.loadAnnotations()}};Store.prototype.annotationCreated=function(annotation){if(__indexOf.call(this.annotations,annotation)<0){this.registerAnnotation(annotation);return this._apiRequest("create",annotation,function(_this){return function(data){if(data.id==null){console.warn(Annotator._t("Warning: No ID returned from server for annotation "),annotation)}return _this.updateAnnotation(annotation,data)}}(this))}else{return this.updateAnnotation(annotation,{})}};Store.prototype.annotationUpdated=function(annotation){if(__indexOf.call(this.annotations,annotation)>=0){return this._apiRequest("update",annotation,function(_this){return function(data){return _this.updateAnnotation(annotation,data)}}(this))}};Store.prototype.annotationDeleted=function(annotation){if(__indexOf.call(this.annotations,annotation)>=0){return this._apiRequest("destroy",annotation,function(_this){return function(){return _this.unregisterAnnotation(annotation)}}(this))}};Store.prototype.registerAnnotation=function(annotation){return this.annotations.push(annotation)};Store.prototype.unregisterAnnotation=function(annotation){return this.annotations.splice(this.annotations.indexOf(annotation),1)};Store.prototype.updateAnnotation=function(annotation,data){if(__indexOf.call(this.annotations,annotation)<0){console.error(Annotator._t("Trying to update unregistered annotation!"))}else{$.extend(annotation,data)}return $(annotation.highlights).data("annotation",annotation)};Store.prototype.loadAnnotations=function(){return this._apiRequest("read",null,this._onLoadAnnotations)};Store.prototype._onLoadAnnotations=function(data){var a,annotation,annotationMap,newData,_k,_l,_len2,_len3,_ref2;if(data==null){data=[]}annotationMap={};_ref2=this.annotations;for(_k=0,_len2=_ref2.length;_k<_len2;_k++){a=_ref2[_k];annotationMap[a.id]=a}newData=[];for(_l=0,_len3=data.length;_l<_len3;_l++){a=data[_l];if(annotationMap[a.id]){annotation=annotationMap[a.id];this.updateAnnotation(annotation,a)}else{newData.push(a)}}this.annotations=this.annotations.concat(newData);return this.annotator.loadAnnotations(newData.slice())};Store.prototype.loadAnnotationsFromSearch=function(searchOptions){return this._apiRequest("search",searchOptions,this._onLoadAnnotationsFromSearch)};Store.prototype._onLoadAnnotationsFromSearch=function(data){if(data==null){data={}}return this._onLoadAnnotations(data.rows||[])};Store.prototype.dumpAnnotations=function(){var ann,_k,_len2,_ref2,_results;_ref2=this.annotations;_results=[];for(_k=0,_len2=_ref2.length;_k<_len2;_k++){ann=_ref2[_k];_results.push(JSON.parse(this._dataFor(ann)))}return _results};Store.prototype._apiRequest=function(action,obj,onSuccess){var id,options,request,url;id=obj&&obj.id;url=this._urlFor(action,id);options=this._apiRequestOptions(action,obj,onSuccess);request=$.ajax(url,options);request._id=id;request._action=action;return request};Store.prototype._apiRequestOptions=function(action,obj,onSuccess){var data,method,opts;method=this._methodFor(action);opts={type:method,headers:this.element.data("annotator:headers"),dataType:"json",success:onSuccess||function(){},error:this._onError};if(this.options.emulateHTTP&&(method==="PUT"||method==="DELETE")){opts.headers=$.extend(opts.headers,{"X-HTTP-Method-Override":method});opts.type="POST"}if(action==="search"){opts=$.extend(opts,{data:obj});return opts}data=obj&&this._dataFor(obj);if(this.options.emulateJSON){opts.data={json:data};if(this.options.emulateHTTP){opts.data._method=method}return opts}opts=$.extend(opts,{data:data,contentType:"application/json; charset=utf-8"});return opts};Store.prototype._urlFor=function(action,id){var url;url=this.options.prefix!=null?this.options.prefix:"";url+=this.options.urls[action];url=url.replace(/\/:id/,id!=null?"/"+id:"");url=url.replace(/:id/,id!=null?id:"");return url};Store.prototype._methodFor=function(action){var table;table={create:"POST",read:"GET",update:"PUT",destroy:"DELETE",search:"GET"};return table[action]};Store.prototype._dataFor=function(annotation){var data,highlights;highlights=annotation.highlights;delete annotation.highlights;$.extend(annotation,this.options.annotationData);data=JSON.stringify(annotation);if(highlights){annotation.highlights=highlights}return data};Store.prototype._onError=function(xhr){var action,message;action=xhr._action;message=Annotator._t("Sorry we could not ")+action+Annotator._t(" this annotation");if(xhr._action==="search"){message=Annotator._t("Sorry we could not search the store for annotations")}else if(xhr._action==="read"&&!xhr._id){message=Annotator._t("Sorry we could not ")+action+Annotator._t(" the annotations from the store")}switch(xhr.status){case 401:message=Annotator._t("Sorry you are not allowed to ")+action+Annotator._t(" this annotation");break;case 404:message=Annotator._t("Sorry we could not connect to the annotations store");break;case 500:message=Annotator._t("Sorry something went wrong with the annotation store")}Annotator.showNotification(message,Annotator.Notification.ERROR);return console.error(Annotator._t("API request failed:")+(" '"+xhr.status+"'"))};return Store}(Annotator.Plugin);Annotator.Plugin.Permissions=function(_super){__extends(Permissions,_super);Permissions.prototype.events={beforeAnnotationCreated:"addFieldsToAnnotation"};Permissions.prototype.options={showViewPermissionsCheckbox:true,showEditPermissionsCheckbox:true,userId:function(user){return user},userString:function(user){return user},userAuthorize:function(action,annotation,user){var token,tokens,_k,_len2;if(annotation.permissions){tokens=annotation.permissions[action]||[];if(tokens.length===0){return true}for(_k=0,_len2=tokens.length;_k<_len2;_k++){token=tokens[_k];if(this.userId(user)===token){return true}}return false}else if(annotation.user){if(user){return this.userId(user)===this.userId(annotation.user)}else{return false}}return true},user:"",permissions:{read:[],update:[],"delete":[],admin:[]}};function Permissions(element,options){this._setAuthFromToken=__bind(this._setAuthFromToken,this);this.updateViewer=__bind(this.updateViewer,this);this.updateAnnotationPermissions=__bind(this.updateAnnotationPermissions,this);this.updatePermissionsField=__bind(this.updatePermissionsField,this);this.addFieldsToAnnotation=__bind(this.addFieldsToAnnotation,this);Permissions.__super__.constructor.apply(this,arguments);if(this.options.user){this.setUser(this.options.user);delete this.options.user}}Permissions.prototype.pluginInit=function(){var createCallback,self;if(!Annotator.supported()){return}self=this;createCallback=function(method,type){return function(field,annotation){return self[method].call(self,type,field,annotation)}};if(!this.user&&this.annotator.plugins.Auth){this.annotator.plugins.Auth.withToken(this._setAuthFromToken)}if(this.options.showViewPermissionsCheckbox===true){this.annotator.editor.addField({type:"checkbox",label:Annotator._t("Allow anyone to <strong>view</strong> this annotation"),load:createCallback("updatePermissionsField","read"),submit:createCallback("updateAnnotationPermissions","read")})}if(this.options.showEditPermissionsCheckbox===true){this.annotator.editor.addField({type:"checkbox",label:Annotator._t("Allow anyone to <strong>edit</strong> this annotation"),load:createCallback("updatePermissionsField","update"),submit:createCallback("updateAnnotationPermissions","update")})}this.annotator.viewer.addField({load:this.updateViewer});if(this.annotator.plugins.Filter){return this.annotator.plugins.Filter.addFilter({label:Annotator._t("User"),property:"user",isFiltered:function(_this){return function(input,user){var keyword,_k,_len2,_ref2;user=_this.options.userString(user);if(!(input&&user)){return false}_ref2=input.split(/\s*/);for(_k=0,_len2=_ref2.length;_k<_len2;_k++){keyword=_ref2[_k];if(user.indexOf(keyword)===-1){return false}}return true}}(this)})}};Permissions.prototype.setUser=function(user){return this.user=user};Permissions.prototype.addFieldsToAnnotation=function(annotation){if(annotation){annotation.permissions=this.options.permissions;if(this.user){return annotation.user=this.user}}};Permissions.prototype.authorize=function(action,annotation,user){if(user===void 0){user=this.user}if(this.options.userAuthorize){return this.options.userAuthorize.call(this.options,action,annotation,user)}else{return true}};Permissions.prototype.updatePermissionsField=function(action,field,annotation){var input;field=$(field).show();input=field.find("input").removeAttr("disabled");if(!this.authorize("admin",annotation)){field.hide()}if(this.authorize(action,annotation||{},null)){return input.attr("checked","checked")}else{return input.removeAttr("checked")}};Permissions.prototype.updateAnnotationPermissions=function(type,field,annotation){var dataKey;if(!annotation.permissions){annotation.permissions=this.options.permissions}dataKey=type+"-permissions";if($(field).find("input").is(":checked")){return annotation.permissions[type]=[]}else{return annotation.permissions[type]=[this.options.userId(this.user)]}};Permissions.prototype.updateViewer=function(field,annotation,controls){var user,username;field=$(field);username=this.options.userString(annotation.user);if(annotation.user&&username&&typeof username==="string"){user=Annotator.Util.escape(this.options.userString(annotation.user));field.html(user).addClass("annotator-user")}else{field.remove()}if(controls){if(!this.authorize("update",annotation)){controls.hideEdit()}if(!this.authorize("delete",annotation)){return controls.hideDelete()}}};Permissions.prototype._setAuthFromToken=function(token){return this.setUser(token.userId)};return Permissions}(Annotator.Plugin);Annotator.Plugin.AnnotateItPermissions=function(_super){__extends(AnnotateItPermissions,_super);function AnnotateItPermissions(){this._setAuthFromToken=__bind(this._setAuthFromToken,this);this.updateAnnotationPermissions=__bind(this.updateAnnotationPermissions,this);this.updatePermissionsField=__bind(this.updatePermissionsField,this);this.addFieldsToAnnotation=__bind(this.addFieldsToAnnotation,this);return AnnotateItPermissions.__super__.constructor.apply(this,arguments)}AnnotateItPermissions.prototype.options={showViewPermissionsCheckbox:true,showEditPermissionsCheckbox:true,groups:{world:"group:__world__",authenticated:"group:__authenticated__",consumer:"group:__consumer__"},userId:function(user){return user.userId},userString:function(user){return user.userId},userAuthorize:function(action,annotation,user){var action_field,permissions,_ref2,_ref3,_ref4,_ref5;permissions=annotation.permissions||{};action_field=permissions[action]||[];if(_ref2=this.groups.world,__indexOf.call(action_field,_ref2)>=0){return true}else if(user!=null&&user.userId!=null&&user.consumerKey!=null){if(user.userId===annotation.user&&user.consumerKey===annotation.consumer){return true}else if(_ref3=this.groups.authenticated,__indexOf.call(action_field,_ref3)>=0){return true}else if(user.consumerKey===annotation.consumer&&(_ref4=this.groups.consumer,__indexOf.call(action_field,_ref4)>=0)){return true}else if(user.consumerKey===annotation.consumer&&(_ref5=user.userId,__indexOf.call(action_field,_ref5)>=0)){return true}else if(user.consumerKey===annotation.consumer&&user.admin){return true}else{return false}}else{return false}},permissions:{read:["group:__world__"],update:[],"delete":[],admin:[]}};AnnotateItPermissions.prototype.addFieldsToAnnotation=function(annotation){if(annotation){annotation.permissions=this.options.permissions;if(this.user){annotation.user=this.user.userId;return annotation.consumer=this.user.consumerKey}}};AnnotateItPermissions.prototype.updatePermissionsField=function(action,field,annotation){var input;field=$(field).show();input=field.find("input").removeAttr("disabled");if(!this.authorize("admin",annotation)){field.hide()}if(this.user&&this.authorize(action,annotation||{},{userId:"__nonexistentuser__",consumerKey:this.user.consumerKey})){return input.attr("checked","checked")}else{return input.removeAttr("checked")}};AnnotateItPermissions.prototype.updateAnnotationPermissions=function(type,field,annotation){var dataKey;if(!annotation.permissions){annotation.permissions=this.options.permissions}dataKey=type+"-permissions";if($(field).find("input").is(":checked")){return annotation.permissions[type]=[type==="read"?this.options.groups.world:this.options.groups.consumer]}else{return annotation.permissions[type]=[]}};AnnotateItPermissions.prototype._setAuthFromToken=function(token){return this.setUser(token)};return AnnotateItPermissions}(Annotator.Plugin.Permissions);Annotator.Plugin.Filter=function(_super){__extends(Filter,_super);Filter.prototype.events={".annotator-filter-property input focus":"_onFilterFocus",".annotator-filter-property input blur":"_onFilterBlur",".annotator-filter-property input keyup":"_onFilterKeyup",".annotator-filter-previous click":"_onPreviousClick",".annotator-filter-next click":"_onNextClick",".annotator-filter-clear click":"_onClearClick"};Filter.prototype.classes={active:"annotator-filter-active",hl:{hide:"annotator-hl-filtered",active:"annotator-hl-active"}};Filter.prototype.html={element:'<div class="annotator-filter">\n  <strong>'+Annotator._t("Navigate:")+'</strong>\n<span class="annotator-filter-navigation">\n  <button class="annotator-filter-previous">'+Annotator._t("Previous")+'</button>\n<button class="annotator-filter-next">'+Annotator._t("Next")+"</button>\n</span>\n<strong>"+Annotator._t("Filter by:")+"</strong>\n</div>",filter:'<span class="annotator-filter-property">\n  <label></label>\n  <input/>\n  <button class="annotator-filter-clear">'+Annotator._t("Clear")+"</button>\n</span>"};
+Filter.prototype.options={appendTo:"body",filters:[],addAnnotationFilter:true,isFiltered:function(input,property){var keyword,_k,_len2,_ref2;if(!(input&&property)){return false}_ref2=input.split(/\s+/);for(_k=0,_len2=_ref2.length;_k<_len2;_k++){keyword=_ref2[_k];if(property.indexOf(keyword)===-1){return false}}return true}};function Filter(element,options){this._onPreviousClick=__bind(this._onPreviousClick,this);this._onNextClick=__bind(this._onNextClick,this);this._onFilterKeyup=__bind(this._onFilterKeyup,this);this._onFilterBlur=__bind(this._onFilterBlur,this);this._onFilterFocus=__bind(this._onFilterFocus,this);this.updateHighlights=__bind(this.updateHighlights,this);var _base;element=$(this.html.element).appendTo((options!=null?options.appendTo:void 0)||this.options.appendTo);Filter.__super__.constructor.call(this,element,options);(_base=this.options).filters||(_base.filters=[]);this.filter=$(this.html.filter);this.filters=[];this.current=0}Filter.prototype.pluginInit=function(){var filter,_k,_len2,_ref2;_ref2=this.options.filters;for(_k=0,_len2=_ref2.length;_k<_len2;_k++){filter=_ref2[_k];this.addFilter(filter)}this.updateHighlights();this._setupListeners()._insertSpacer();if(this.options.addAnnotationFilter===true){return this.addFilter({label:Annotator._t("Annotation"),property:"text"})}};Filter.prototype.destroy=function(){var currentMargin,html;Filter.__super__.destroy.apply(this,arguments);html=$("html");currentMargin=parseInt(html.css("padding-top"),10)||0;html.css("padding-top",currentMargin-this.element.outerHeight());return this.element.remove()};Filter.prototype._insertSpacer=function(){var currentMargin,html;html=$("html");currentMargin=parseInt(html.css("padding-top"),10)||0;html.css("padding-top",currentMargin+this.element.outerHeight());return this};Filter.prototype._setupListeners=function(){var event,events,_k,_len2;events=["annotationsLoaded","annotationCreated","annotationUpdated","annotationDeleted"];for(_k=0,_len2=events.length;_k<_len2;_k++){event=events[_k];this.annotator.subscribe(event,this.updateHighlights)}return this};Filter.prototype.addFilter=function(options){var f,filter;filter=$.extend({label:"",property:"",isFiltered:this.options.isFiltered},options);if(!function(){var _k,_len2,_ref2,_results;_ref2=this.filters;_results=[];for(_k=0,_len2=_ref2.length;_k<_len2;_k++){f=_ref2[_k];if(f.property===filter.property){_results.push(f)}}return _results}.call(this).length){filter.id="annotator-filter-"+filter.property;filter.annotations=[];filter.element=this.filter.clone().appendTo(this.element);filter.element.find("label").html(filter.label).attr("for",filter.id);filter.element.find("input").attr({id:filter.id,placeholder:Annotator._t("Filter by ")+filter.label+"…"});filter.element.find("button").hide();filter.element.data("filter",filter);this.filters.push(filter)}return this};Filter.prototype.updateFilter=function(filter){var annotation,annotations,input,property,_k,_len2,_ref2;filter.annotations=[];this.updateHighlights();this.resetHighlights();input=$.trim(filter.element.find("input").val());if(input){annotations=this.highlights.map(function(){return $(this).data("annotation")});_ref2=$.makeArray(annotations);for(_k=0,_len2=_ref2.length;_k<_len2;_k++){annotation=_ref2[_k];property=annotation[filter.property];if(filter.isFiltered(input,property)){filter.annotations.push(annotation)}}return this.filterHighlights()}};Filter.prototype.updateHighlights=function(){this.highlights=this.annotator.element.find(".annotator-hl:visible");return this.filtered=this.highlights.not(this.classes.hl.hide)};Filter.prototype.filterHighlights=function(){var activeFilters,annotation,annotations,filtered,highlights,index,uniques,_k,_len2,_ref2;activeFilters=$.grep(this.filters,function(filter){return!!filter.annotations.length});filtered=((_ref2=activeFilters[0])!=null?_ref2.annotations:void 0)||[];if(activeFilters.length>1){annotations=[];$.each(activeFilters,function(){return $.merge(annotations,this.annotations)});uniques=[];filtered=[];$.each(annotations,function(){if($.inArray(this,uniques)===-1){return uniques.push(this)}else{return filtered.push(this)}})}highlights=this.highlights;for(index=_k=0,_len2=filtered.length;_k<_len2;index=++_k){annotation=filtered[index];highlights=highlights.not(annotation.highlights)}highlights.addClass(this.classes.hl.hide);this.filtered=this.highlights.not(this.classes.hl.hide);return this};Filter.prototype.resetHighlights=function(){this.highlights.removeClass(this.classes.hl.hide);this.filtered=this.highlights;return this};Filter.prototype._onFilterFocus=function(event){var input;input=$(event.target);input.parent().addClass(this.classes.active);return input.next("button").show()};Filter.prototype._onFilterBlur=function(event){var input;if(!event.target.value){input=$(event.target);input.parent().removeClass(this.classes.active);return input.next("button").hide()}};Filter.prototype._onFilterKeyup=function(event){var filter;filter=$(event.target).parent().data("filter");if(filter){return this.updateFilter(filter)}};Filter.prototype._findNextHighlight=function(previous){var active,annotation,current,index,next,offset,operator,resetOffset;if(!this.highlights.length){return this}offset=previous?0:-1;resetOffset=previous?-1:0;operator=previous?"lt":"gt";active=this.highlights.not("."+this.classes.hl.hide);current=active.filter("."+this.classes.hl.active);if(!current.length){current=active.eq(offset)}annotation=current.data("annotation");index=active.index(current[0]);next=active.filter(":"+operator+"("+index+")").not(annotation.highlights).eq(resetOffset);if(!next.length){next=active.eq(resetOffset)}return this._scrollToHighlight(next.data("annotation").highlights)};Filter.prototype._onNextClick=function(event){return this._findNextHighlight()};Filter.prototype._onPreviousClick=function(event){return this._findNextHighlight(true)};Filter.prototype._scrollToHighlight=function(highlight){highlight=$(highlight);this.highlights.removeClass(this.classes.hl.active);highlight.addClass(this.classes.hl.active);return $("html, body").animate({scrollTop:highlight.offset().top-(this.element.height()+20)},150)};Filter.prototype._onClearClick=function(event){return $(event.target).prev("input").val("").keyup().blur()};return Filter}(Annotator.Plugin);Annotator.Plugin.Markdown=function(_super){__extends(Markdown,_super);Markdown.prototype.events={annotationViewerTextField:"updateTextField"};function Markdown(element,options){this.updateTextField=__bind(this.updateTextField,this);if((typeof Showdown!=="undefined"&&Showdown!==null?Showdown.converter:void 0)!=null){Markdown.__super__.constructor.apply(this,arguments);this.converter=new Showdown.converter}else{console.error(Annotator._t("To use the Markdown plugin, you must include Showdown into the page first."))}}Markdown.prototype.updateTextField=function(field,annotation){var text;text=Annotator.Util.escape(annotation.text||"");return $(field).html(this.convert(text))};Markdown.prototype.convert=function(text){return this.converter.makeHtml(text)};return Markdown}(Annotator.Plugin);Annotator.Plugin.Tags=function(_super){__extends(Tags,_super);function Tags(){this.setAnnotationTags=__bind(this.setAnnotationTags,this);this.updateField=__bind(this.updateField,this);return Tags.__super__.constructor.apply(this,arguments)}Tags.prototype.options={parseTags:function(string){var tags;string=$.trim(string);tags=[];if(string){tags=string.split(/\s+/)}return tags},stringifyTags:function(array){return array.join(" ")}};Tags.prototype.field=null;Tags.prototype.input=null;Tags.prototype.pluginInit=function(){if(!Annotator.supported()){return}this.field=this.annotator.editor.addField({label:Annotator._t("Add some tags here")+"…",load:this.updateField,submit:this.setAnnotationTags});this.annotator.viewer.addField({load:this.updateViewer});if(this.annotator.plugins.Filter){this.annotator.plugins.Filter.addFilter({label:Annotator._t("Tag"),property:"tags",isFiltered:Annotator.Plugin.Tags.filterCallback})}return this.input=$(this.field).find(":input")};Tags.prototype.parseTags=function(string){return this.options.parseTags(string)};Tags.prototype.stringifyTags=function(array){return this.options.stringifyTags(array)};Tags.prototype.updateField=function(field,annotation){var value;value="";if(annotation.tags){value=this.stringifyTags(annotation.tags)}return this.input.val(value)};Tags.prototype.setAnnotationTags=function(field,annotation){return annotation.tags=this.parseTags(this.input.val())};Tags.prototype.updateViewer=function(field,annotation){field=$(field);if(annotation.tags&&$.isArray(annotation.tags)&&annotation.tags.length){return field.addClass("annotator-tags").html(function(){var string;return string=$.map(annotation.tags,function(tag){return'<span class="annotator-tag">'+Annotator.Util.escape(tag)+"</span>"}).join(" ")})}else{return field.remove()}};return Tags}(Annotator.Plugin);Annotator.Plugin.Tags.filterCallback=function(input,tags){var keyword,keywords,matches,tag,_k,_l,_len2,_len3;if(tags==null){tags=[]}matches=0;keywords=[];if(input){keywords=input.split(/\s+/g);for(_k=0,_len2=keywords.length;_k<_len2;_k++){keyword=keywords[_k];if(tags.length){for(_l=0,_len3=tags.length;_l<_len3;_l++){tag=tags[_l];if(tag.indexOf(keyword)!==-1){matches+=1}}}}}return matches===keywords.length};Annotator.prototype.setupPlugins=function(config,options){var name,opts,pluginConfig,plugins,uri,win,_k,_len2,_results;if(config==null){config={}}if(options==null){options={}}win=Annotator.Util.getGlobal();plugins=["Unsupported","Auth","Tags","Filter","Store","AnnotateItPermissions"];if(win.Showdown){plugins.push("Markdown")}uri=win.location.href.split(/#|\?/).shift()||"";pluginConfig={Tags:{},Filter:{filters:[{label:Annotator._t("User"),property:"user"},{label:Annotator._t("Tags"),property:"tags"}]},Auth:{tokenUrl:config.tokenUrl||"http://annotateit.org/api/token"},Store:{prefix:config.storeUrl||"http://annotateit.org/api",annotationData:{uri:uri},loadFromSearch:{uri:uri}}};for(name in options){if(!__hasProp.call(options,name))continue;opts=options[name];if(__indexOf.call(plugins,name)<0){plugins.push(name)}}$.extend(true,pluginConfig,options);_results=[];for(_k=0,_len2=plugins.length;_k<_len2;_k++){name=plugins[_k];if(!(name in pluginConfig)||pluginConfig[name]){_results.push(this.addPlugin(name,pluginConfig[name]))}else{_results.push(void 0)}}return _results}}.call(this);
+//
\ No newline at end of file
diff --git a/karmaworld/assets/js/foundation.joyride.js b/karmaworld/assets/js/foundation.joyride.js
new file mode 100644 (file)
index 0000000..401414c
--- /dev/null
@@ -0,0 +1,844 @@
+;(function ($, window, document, undefined) {
+  'use strict';
+
+  var Modernizr = Modernizr || false;
+
+  Foundation.libs.joyride = {
+    name : 'joyride',
+
+    version : '5.2.1',
+
+    defaults : {
+      expose                   : false,     // turn on or off the expose feature
+      modal                    : true,      // Whether to cover page with modal during the tour
+      tip_location             : 'bottom',  // 'top' or 'bottom' in relation to parent
+      nub_position             : 'auto',    // override on a per tooltip bases
+      scroll_speed             : 1500,      // Page scrolling speed in milliseconds, 0 = no scroll animation
+      scroll_animation         : 'linear',  // supports 'swing' and 'linear', extend with jQuery UI.
+      timer                    : 0,         // 0 = no timer , all other numbers = timer in milliseconds
+      start_timer_on_click     : true,      // true or false - true requires clicking the first button start the timer
+      start_offset             : 0,         // the index of the tooltip you want to start on (index of the li)
+      next_button              : true,      // true or false to control whether a next button is used
+      tip_animation            : 'fade',    // 'pop' or 'fade' in each tip
+      pause_after              : [],        // array of indexes where to pause the tour after
+      exposed                  : [],        // array of expose elements
+      tip_animation_fade_speed : 300,       // when tipAnimation = 'fade' this is speed in milliseconds for the transition
+      cookie_monster           : false,     // true or false to control whether cookies are used
+      cookie_name              : 'joyride', // Name the cookie you'll use
+      cookie_domain            : false,     // Will this cookie be attached to a domain, ie. '.notableapp.com'
+      cookie_expires           : 365,       // set when you would like the cookie to expire.
+      tip_container            : 'body',    // Where will the tip be attached
+      tip_location_patterns    : {
+        top: ['bottom'],
+        bottom: [], // bottom should not need to be repositioned
+        left: ['right', 'top', 'bottom'],
+        right: ['left', 'top', 'bottom']
+      },
+      post_ride_callback     : function (){},    // A method to call once the tour closes (canceled or complete)
+      post_step_callback     : function (){},    // A method to call after each step
+      pre_step_callback      : function (){},    // A method to call before each step
+      pre_ride_callback      : function (){},    // A method to call before the tour starts (passed index, tip, and cloned exposed element)
+      post_expose_callback   : function (){},    // A method to call after an element has been exposed
+      template : { // HTML segments for tip layout
+        link    : '<a href="#close" class="joyride-close-tip">&times;</a>',
+        timer   : '<div class="joyride-timer-indicator-wrap"><span class="joyride-timer-indicator"></span></div>',
+        tip     : '<div class="joyride-tip-guide"><span class="joyride-nub"></span></div>',
+        wrapper : '<div class="joyride-content-wrapper"></div>',
+        button  : '<a href="#" class="small button joyride-next-tip"></a>',
+        modal   : '<div class="joyride-modal-bg"></div>',
+        expose  : '<div class="joyride-expose-wrapper"></div>',
+        expose_cover: '<div class="joyride-expose-cover"></div>'
+      },
+      expose_add_class : '' // One or more space-separated class names to be added to exposed element
+    },
+
+    init : function (scope, method, options) {
+      Foundation.inherit(this, 'throttle random_str');
+
+      this.settings = this.settings || $.extend({}, this.defaults, (options || method));
+
+      this.bindings(method, options)
+    },
+
+    events : function () {
+      var self = this;
+
+      $(this.scope)
+        .off('.joyride')
+        .on('click.fndtn.joyride', '.joyride-next-tip, .joyride-modal-bg', function (e) {
+          e.preventDefault();
+
+          if (this.settings.$li.next().length < 1) {
+            this.end();
+          } else if (this.settings.timer > 0) {
+            clearTimeout(this.settings.automate);
+            this.hide();
+            this.show();
+            this.startTimer();
+          } else {
+            this.hide();
+            this.show();
+          }
+
+        }.bind(this))
+
+        .on('click.fndtn.joyride', '.joyride-close-tip', function (e) {
+          e.preventDefault();
+          this.end();
+        }.bind(this));
+
+      $(window)
+        .off('.joyride')
+        .on('resize.fndtn.joyride', self.throttle(function () {
+          if ($('[' + self.attr_name() + ']').length > 0 && self.settings.$next_tip) {
+            if (self.settings.exposed.length > 0) {
+              var $els = $(self.settings.exposed);
+
+              $els.each(function () {
+                var $this = $(this);
+                self.un_expose($this);
+                self.expose($this);
+              });
+            }
+
+            if (self.is_phone()) {
+              self.pos_phone();
+            } else {
+              self.pos_default(false, true);
+            }
+          }
+        }, 100));
+    },
+
+    start : function () {
+      var self = this,
+          $this = $('[' + this.attr_name() + ']', this.scope),
+          integer_settings = ['timer', 'scrollSpeed', 'startOffset', 'tipAnimationFadeSpeed', 'cookieExpires'],
+          int_settings_count = integer_settings.length;
+
+      if (!$this.length > 0) return;
+
+      if (!this.settings.init) this.events();
+
+      this.settings = $this.data(this.attr_name(true) + '-init');
+
+      // non configureable settings
+      this.settings.$content_el = $this;
+      this.settings.$body = $(this.settings.tip_container);
+      this.settings.body_offset = $(this.settings.tip_container).position();
+      this.settings.$tip_content = this.settings.$content_el.find('> li');
+      this.settings.paused = false;
+      this.settings.attempts = 0;
+
+      // can we create cookies?
+      if (typeof $.cookie !== 'function') {
+        this.settings.cookie_monster = false;
+      }
+
+      // generate the tips and insert into dom.
+      if (!this.settings.cookie_monster || this.settings.cookie_monster && !$.cookie(this.settings.cookie_name)) {
+        this.settings.$tip_content.each(function (index) {
+          var $this = $(this);
+          this.settings = $.extend({}, self.defaults, self.data_options($this))
+
+          // Make sure that settings parsed from data_options are integers where necessary
+          var i = int_settings_count;
+          while (i--) {
+            self.settings[integer_settings[i]] = parseInt(self.settings[integer_settings[i]], 10);
+          }
+          self.create({$li : $this, index : index});
+        });
+
+        // show first tip
+        if (!this.settings.start_timer_on_click && this.settings.timer > 0) {
+          this.show('init');
+          this.startTimer();
+        } else {
+          this.show('init');
+        }
+
+      }
+    },
+
+    resume : function () {
+      this.set_li();
+      this.show();
+    },
+
+    tip_template : function (opts) {
+      var $blank, content;
+
+      opts.tip_class = opts.tip_class || '';
+
+      $blank = $(this.settings.template.tip).addClass(opts.tip_class);
+      content = $.trim($(opts.li).html()) +
+        this.button_text(opts.button_text) +
+        this.settings.template.link +
+        this.timer_instance(opts.index);
+
+      $blank.append($(this.settings.template.wrapper));
+      $blank.first().attr(this.add_namespace('data-index'), opts.index);
+      $('.joyride-content-wrapper', $blank).append(content);
+
+      return $blank[0];
+    },
+
+    timer_instance : function (index) {
+      var txt;
+
+      if ((index === 0 && this.settings.start_timer_on_click && this.settings.timer > 0) || this.settings.timer === 0) {
+        txt = '';
+      } else {
+        txt = $(this.settings.template.timer)[0].outerHTML;
+      }
+      return txt;
+    },
+
+    button_text : function (txt) {
+      if (this.settings.next_button) {
+        txt = $.trim(txt) || 'Next';
+        txt = $(this.settings.template.button).append(txt)[0].outerHTML;
+      } else {
+        txt = '';
+      }
+      return txt;
+    },
+
+    create : function (opts) {
+      var buttonText = opts.$li.attr(this.add_namespace('data-button')) 
+        || opts.$li.attr(this.add_namespace('data-text')),
+        tipClass = opts.$li.attr('class'),
+        $tip_content = $(this.tip_template({
+          tip_class : tipClass,
+          index : opts.index,
+          button_text : buttonText,
+          li : opts.$li
+        }));
+
+      $(this.settings.tip_container).append($tip_content);
+    },
+
+    show : function (init) {
+      var $timer = null;
+
+      // are we paused?
+      if (this.settings.$li === undefined
+        || ($.inArray(this.settings.$li.index(), this.settings.pause_after) === -1)) {
+
+        // don't go to the next li if the tour was paused
+        if (this.settings.paused) {
+          this.settings.paused = false;
+        } else {
+          this.set_li(init);
+        }
+
+        this.settings.attempts = 0;
+
+        if (this.settings.$li.length && this.settings.$target.length > 0) {
+          if (init) { //run when we first start
+            this.settings.pre_ride_callback(this.settings.$li.index(), this.settings.$next_tip);
+            if (this.settings.modal) {
+              this.show_modal();
+            }
+          }
+
+          this.settings.pre_step_callback(this.settings.$li.index(), this.settings.$next_tip);
+
+          if (this.settings.modal && this.settings.expose) {
+            this.expose();
+          }
+
+          this.settings.tip_settings = $.extend({}, this.settings, this.data_options(this.settings.$li));
+
+          this.settings.timer = parseInt(this.settings.timer, 10);
+
+          this.settings.tip_settings.tip_location_pattern = this.settings.tip_location_patterns[this.settings.tip_settings.tip_location];
+
+          // scroll if not modal
+          if (!/body/i.test(this.settings.$target.selector)) {
+            this.scroll_to();
+          }
+
+          if (this.is_phone()) {
+            this.pos_phone(true);
+          } else {
+            this.pos_default(true);
+          }
+
+          $timer = this.settings.$next_tip.find('.joyride-timer-indicator');
+
+          if (/pop/i.test(this.settings.tip_animation)) {
+
+            $timer.width(0);
+
+            if (this.settings.timer > 0) {
+
+              this.settings.$next_tip.show();
+
+              setTimeout(function () {
+                $timer.animate({
+                  width: $timer.parent().width()
+                }, this.settings.timer, 'linear');
+              }.bind(this), this.settings.tip_animation_fade_speed);
+
+            } else {
+              this.settings.$next_tip.show();
+
+            }
+
+
+          } else if (/fade/i.test(this.settings.tip_animation)) {
+
+            $timer.width(0);
+
+            if (this.settings.timer > 0) {
+
+              this.settings.$next_tip
+                .fadeIn(this.settings.tip_animation_fade_speed)
+                .show();
+
+              setTimeout(function () {
+                $timer.animate({
+                  width: $timer.parent().width()
+                }, this.settings.timer, 'linear');
+              }.bind(this), this.settings.tip_animation_fadeSpeed);
+
+            } else {
+              this.settings.$next_tip.fadeIn(this.settings.tip_animation_fade_speed);
+            }
+          }
+
+          this.settings.$current_tip = this.settings.$next_tip;
+
+        // skip non-existant targets
+        } else if (this.settings.$li && this.settings.$target.length < 1) {
+
+          this.show();
+
+        } else {
+
+          this.end();
+
+        }
+      } else {
+
+        this.settings.paused = true;
+
+      }
+
+    },
+
+    is_phone : function () {
+      return matchMedia(Foundation.media_queries.small).matches &&
+        !matchMedia(Foundation.media_queries.medium).matches;
+    },
+
+    hide : function () {
+      if (this.settings.modal && this.settings.expose) {
+        this.un_expose();
+      }
+
+      if (!this.settings.modal) {
+        $('.joyride-modal-bg').hide();
+      }
+
+      // Prevent scroll bouncing...wait to remove from layout
+      this.settings.$current_tip.css('visibility', 'hidden');
+      setTimeout($.proxy(function() {
+        this.hide();
+        this.css('visibility', 'visible');
+      }, this.settings.$current_tip), 0);
+      this.settings.post_step_callback(this.settings.$li.index(),
+        this.settings.$current_tip);
+    },
+
+    set_li : function (init) {
+      if (init) {
+        this.settings.$li = this.settings.$tip_content.eq(this.settings.start_offset);
+        this.set_next_tip();
+        this.settings.$current_tip = this.settings.$next_tip;
+      } else {
+        this.settings.$li = this.settings.$li.next();
+        this.set_next_tip();
+      }
+
+      this.set_target();
+    },
+
+    set_next_tip : function () {
+      this.settings.$next_tip = $(".joyride-tip-guide").eq(this.settings.$li.index());
+      this.settings.$next_tip.data('closed', '');
+    },
+
+    set_target : function () {
+      var cl = this.settings.$li.attr(this.add_namespace('data-class')),
+          id = this.settings.$li.attr(this.add_namespace('data-id')),
+          $sel = function () {
+            if (id) {
+              return $(document.getElementById(id));
+            } else if (cl) {
+              return $('.' + cl).first();
+            } else {
+              return $('body');
+            }
+          };
+
+      this.settings.$target = $sel();
+    },
+
+    scroll_to : function () {
+      var window_half, tipOffset;
+
+      window_half = $(window).height() / 2;
+      tipOffset = Math.ceil(this.settings.$target.offset().top - window_half + this.settings.$next_tip.outerHeight());
+
+      if (tipOffset != 0) {
+        $('html, body').animate({
+          scrollTop: tipOffset
+        }, this.settings.scroll_speed, 'swing');
+      }
+    },
+
+    paused : function () {
+      return ($.inArray((this.settings.$li.index() + 1), this.settings.pause_after) === -1);
+    },
+
+    restart : function () {
+      this.hide();
+      this.settings.$li = undefined;
+      this.show('init');
+    },
+
+    pos_default : function (init, resizing) {
+      var half_fold = Math.ceil($(window).height() / 2),
+          tip_position = this.settings.$next_tip.offset(),
+          $nub = this.settings.$next_tip.find('.joyride-nub'),
+          nub_width = Math.ceil($nub.outerWidth() / 2),
+          nub_height = Math.ceil($nub.outerHeight() / 2),
+          toggle = init || false;
+
+      // tip must not be "display: none" to calculate position
+      if (toggle) {
+        this.settings.$next_tip.css('visibility', 'hidden');
+        this.settings.$next_tip.show();
+      }
+
+      if (typeof resizing === 'undefined') {
+        resizing = false;
+      }
+
+      if (!/body/i.test(this.settings.$target.selector)) {
+          if (this.bottom()) {
+            if (this.rtl) {
+              this.settings.$next_tip.css({
+                top: (this.settings.$target.offset().top + nub_height + this.settings.$target.outerHeight()),
+                left: this.settings.$target.offset().left + this.settings.$target.outerWidth() - this.settings.$next_tip.outerWidth()});
+            } else {
+              this.settings.$next_tip.css({
+                top: (this.settings.$target.offset().top + nub_height + this.settings.$target.outerHeight()),
+                left: this.settings.$target.offset().left});
+            }
+
+            this.nub_position($nub, this.settings.tip_settings.nub_position, 'top');
+
+          } else if (this.top()) {
+            if (this.rtl) {
+              this.settings.$next_tip.css({
+                top: (this.settings.$target.offset().top - this.settings.$next_tip.outerHeight() - nub_height),
+                left: this.settings.$target.offset().left + this.settings.$target.outerWidth() - this.settings.$next_tip.outerWidth()});
+            } else {
+              this.settings.$next_tip.css({
+                top: (this.settings.$target.offset().top - this.settings.$next_tip.outerHeight() - nub_height),
+                left: this.settings.$target.offset().left});
+            }
+
+            this.nub_position($nub, this.settings.tip_settings.nub_position, 'bottom');
+
+          } else if (this.right()) {
+
+            this.settings.$next_tip.css({
+              top: this.settings.$target.offset().top,
+              left: (this.settings.$target.outerWidth() + this.settings.$target.offset().left + nub_width)});
+
+            this.nub_position($nub, this.settings.tip_settings.nub_position, 'left');
+
+          } else if (this.left()) {
+
+            this.settings.$next_tip.css({
+              top: this.settings.$target.offset().top,
+              left: (this.settings.$target.offset().left - this.settings.$next_tip.outerWidth() - nub_width)});
+
+            this.nub_position($nub, this.settings.tip_settings.nub_position, 'right');
+
+          }
+
+          if (!this.visible(this.corners(this.settings.$next_tip)) && this.settings.attempts < this.settings.tip_settings.tip_location_pattern.length) {
+
+            $nub.removeClass('bottom')
+              .removeClass('top')
+              .removeClass('right')
+              .removeClass('left');
+
+            this.settings.tip_settings.tip_location = this.settings.tip_settings.tip_location_pattern[this.settings.attempts];
+
+            this.settings.attempts++;
+
+            this.pos_default();
+
+          }
+
+      } else if (this.settings.$li.length) {
+
+        this.pos_modal($nub);
+
+      }
+
+      if (toggle) {
+        this.settings.$next_tip.hide();
+        this.settings.$next_tip.css('visibility', 'visible');
+      }
+
+    },
+
+    pos_phone : function (init) {
+      var tip_height = this.settings.$next_tip.outerHeight(),
+          tip_offset = this.settings.$next_tip.offset(),
+          target_height = this.settings.$target.outerHeight(),
+          $nub = $('.joyride-nub', this.settings.$next_tip),
+          nub_height = Math.ceil($nub.outerHeight() / 2),
+          toggle = init || false;
+
+      $nub.removeClass('bottom')
+        .removeClass('top')
+        .removeClass('right')
+        .removeClass('left');
+
+      if (toggle) {
+        this.settings.$next_tip.css('visibility', 'hidden');
+        this.settings.$next_tip.show();
+      }
+
+      if (!/body/i.test(this.settings.$target.selector)) {
+
+        if (this.top()) {
+
+            this.settings.$next_tip.offset({top: this.settings.$target.offset().top - tip_height - nub_height});
+            $nub.addClass('bottom');
+
+        } else {
+
+          this.settings.$next_tip.offset({top: this.settings.$target.offset().top + target_height + nub_height});
+          $nub.addClass('top');
+
+        }
+
+      } else if (this.settings.$li.length) {
+        this.pos_modal($nub);
+      }
+
+      if (toggle) {
+        this.settings.$next_tip.hide();
+        this.settings.$next_tip.css('visibility', 'visible');
+      }
+    },
+
+    pos_modal : function ($nub) {
+      this.center();
+      $nub.hide();
+
+      this.show_modal();
+    },
+
+    show_modal : function () {
+      if (!this.settings.$next_tip.data('closed')) {
+        var joyridemodalbg =  $('.joyride-modal-bg');
+        if (joyridemodalbg.length < 1) {
+          $('body').append(this.settings.template.modal).show();
+        }
+
+        if (/pop/i.test(this.settings.tip_animation)) {
+            joyridemodalbg.show();
+        } else {
+            joyridemodalbg.fadeIn(this.settings.tip_animation_fade_speed);
+        }
+      }
+    },
+
+    expose : function () {
+      var expose,
+          exposeCover,
+          el,
+          origCSS,
+          origClasses,
+          randId = 'expose-' + this.random_str(6);
+
+      if (arguments.length > 0 && arguments[0] instanceof $) {
+        el = arguments[0];
+      } else if(this.settings.$target && !/body/i.test(this.settings.$target.selector)){
+        el = this.settings.$target;
+      }  else {
+        return false;
+      }
+
+      if(el.length < 1){
+        if(window.console){
+          console.error('element not valid', el);
+        }
+        return false;
+      }
+
+      expose = $(this.settings.template.expose);
+      this.settings.$body.append(expose);
+      expose.css({
+        top: el.offset().top,
+        left: el.offset().left,
+        width: el.outerWidth(true),
+        height: el.outerHeight(true)
+      });
+
+      exposeCover = $(this.settings.template.expose_cover);
+
+      origCSS = {
+        zIndex: el.css('z-index'),
+        position: el.css('position')
+      };
+
+      origClasses = el.attr('class') == null ? '' : el.attr('class');
+
+      el.css('z-index',parseInt(expose.css('z-index'))+1);
+
+      if (origCSS.position == 'static') {
+        el.css('position','relative');
+      }
+
+      el.data('expose-css',origCSS);
+      el.data('orig-class', origClasses);
+      el.attr('class', origClasses + ' ' + this.settings.expose_add_class);
+
+      exposeCover.css({
+        top: el.offset().top,
+        left: el.offset().left,
+        width: el.outerWidth(true),
+        height: el.outerHeight(true)
+      });
+
+      if (this.settings.modal) this.show_modal();
+
+      this.settings.$body.append(exposeCover);
+      expose.addClass(randId);
+      exposeCover.addClass(randId);
+      el.data('expose', randId);
+      this.settings.post_expose_callback(this.settings.$li.index(), this.settings.$next_tip, el);
+      this.add_exposed(el);
+    },
+
+    un_expose : function () {
+      var exposeId,
+          el,
+          expose ,
+          origCSS,
+          origClasses,
+          clearAll = false;
+
+      if (arguments.length > 0 && arguments[0] instanceof $) {
+        el = arguments[0];
+      } else if(this.settings.$target && !/body/i.test(this.settings.$target.selector)){
+        el = this.settings.$target;
+      }  else {
+        return false;
+      }
+
+      if(el.length < 1){
+        if (window.console) {
+          console.error('element not valid', el);
+        }
+        return false;
+      }
+
+      exposeId = el.data('expose');
+      expose = $('.' + exposeId);
+
+      if (arguments.length > 1) {
+        clearAll = arguments[1];
+      }
+
+      if (clearAll === true) {
+        $('.joyride-expose-wrapper,.joyride-expose-cover').remove();
+      } else {
+        expose.remove();
+      }
+
+      origCSS = el.data('expose-css');
+
+      if (origCSS.zIndex == 'auto') {
+        el.css('z-index', '');
+      } else {
+        el.css('z-index', origCSS.zIndex);
+      }
+
+      if (origCSS.position != el.css('position')) {
+        if(origCSS.position == 'static') {// this is default, no need to set it.
+          el.css('position', '');
+        } else {
+          el.css('position', origCSS.position);
+        }
+      }
+
+      origClasses = el.data('orig-class');
+      el.attr('class', origClasses);
+      el.removeData('orig-classes');
+
+      el.removeData('expose');
+      el.removeData('expose-z-index');
+      this.remove_exposed(el);
+    },
+
+    add_exposed: function(el){
+      this.settings.exposed = this.settings.exposed || [];
+      if (el instanceof $ || typeof el === 'object') {
+        this.settings.exposed.push(el[0]);
+      } else if (typeof el == 'string') {
+        this.settings.exposed.push(el);
+      }
+    },
+
+    remove_exposed: function(el){
+      var search, i;
+      if (el instanceof $) {
+        search = el[0]
+      } else if (typeof el == 'string'){
+        search = el;
+      }
+
+      this.settings.exposed = this.settings.exposed || [];
+      i = this.settings.exposed.length;
+
+      while (i--) {
+        if (this.settings.exposed[i] == search) {
+          this.settings.exposed.splice(i, 1);
+          return;
+        }
+      }
+    },
+
+    center : function () {
+      var $w = $(window);
+
+      this.settings.$next_tip.css({
+        top : ((($w.height() - this.settings.$next_tip.outerHeight()) / 2) + $w.scrollTop()),
+        left : ((($w.width() - this.settings.$next_tip.outerWidth()) / 2) + $w.scrollLeft())
+      });
+
+      return true;
+    },
+
+    bottom : function () {
+      return /bottom/i.test(this.settings.tip_settings.tip_location);
+    },
+
+    top : function () {
+      return /top/i.test(this.settings.tip_settings.tip_location);
+    },
+
+    right : function () {
+      return /right/i.test(this.settings.tip_settings.tip_location);
+    },
+
+    left : function () {
+      return /left/i.test(this.settings.tip_settings.tip_location);
+    },
+
+    corners : function (el) {
+      var w = $(window),
+          window_half = w.height() / 2,
+          //using this to calculate since scroll may not have finished yet.
+          tipOffset = Math.ceil(this.settings.$target.offset().top - window_half + this.settings.$next_tip.outerHeight()),
+          right = w.width() + w.scrollLeft(),
+          offsetBottom =  w.height() + tipOffset,
+          bottom = w.height() + w.scrollTop(),
+          top = w.scrollTop();
+
+      if (tipOffset < top) {
+        if (tipOffset < 0) {
+          top = 0;
+        } else {
+          top = tipOffset;
+        }
+      }
+
+      if (offsetBottom > bottom) {
+        bottom = offsetBottom;
+      }
+
+      return [
+        el.offset().top < top,
+        right < el.offset().left + el.outerWidth(),
+        bottom < el.offset().top + el.outerHeight(),
+        w.scrollLeft() > el.offset().left
+      ];
+    },
+
+    visible : function (hidden_corners) {
+      var i = hidden_corners.length;
+
+      while (i--) {
+        if (hidden_corners[i]) return false;
+      }
+
+      return true;
+    },
+
+    nub_position : function (nub, pos, def) {
+      if (pos === 'auto') {
+        nub.addClass(def);
+      } else {
+        nub.addClass(pos);
+      }
+    },
+
+    startTimer : function () {
+      if (this.settings.$li.length) {
+        this.settings.automate = setTimeout(function () {
+          this.hide();
+          this.show();
+          this.startTimer();
+        }.bind(this), this.settings.timer);
+      } else {
+        clearTimeout(this.settings.automate);
+      }
+    },
+
+    end : function () {
+      if (this.settings.cookie_monster) {
+        $.cookie(this.settings.cookie_name, 'ridden', { expires: this.settings.cookie_expires, domain: this.settings.cookie_domain });
+      }
+
+      if (this.settings.timer > 0) {
+        clearTimeout(this.settings.automate);
+      }
+
+      if (this.settings.modal && this.settings.expose) {
+        this.un_expose();
+      }
+
+      this.settings.$next_tip.data('closed', true);
+
+      $('.joyride-modal-bg').hide();
+      this.settings.$current_tip.hide();
+      this.settings.post_step_callback(this.settings.$li.index(), this.settings.$current_tip);
+      this.settings.post_ride_callback(this.settings.$li.index(), this.settings.$current_tip);
+      $('.joyride-tip-guide').remove();
+    },
+
+    off : function () {
+      $(this.scope).off('.joyride');
+      $(window).off('.joyride');
+      $('.joyride-close-tip, .joyride-next-tip, .joyride-modal-bg').off('.joyride');
+      $('.joyride-tip-guide, .joyride-modal-bg').remove();
+      clearTimeout(this.settings.automate);
+      this.settings = {};
+    },
+
+    reflow : function () {}
+  };
+}(jQuery, this, this.document));
diff --git a/karmaworld/assets/js/jquery.cookie.js b/karmaworld/assets/js/jquery.cookie.js
new file mode 100644 (file)
index 0000000..9271900
--- /dev/null
@@ -0,0 +1,117 @@
+/*!
+ * jQuery Cookie Plugin v1.4.0
+ * https://github.com/carhartl/jquery-cookie
+ *
+ * Copyright 2013 Klaus Hartl
+ * Released under the MIT license
+ */
+(function (factory) {
+       if (typeof define === 'function' && define.amd) {
+               // AMD. Register as anonymous module.
+               define(['jquery'], factory);
+       } else {
+               // Browser globals.
+               factory(jQuery);
+       }
+}(function ($) {
+
+       var pluses = /\+/g;
+
+       function encode(s) {
+               return config.raw ? s : encodeURIComponent(s);
+       }
+
+       function decode(s) {
+               return config.raw ? s : decodeURIComponent(s);
+       }
+
+       function stringifyCookieValue(value) {
+               return encode(config.json ? JSON.stringify(value) : String(value));
+       }
+
+       function parseCookieValue(s) {
+               if (s.indexOf('"') === 0) {
+                       // This is a quoted cookie as according to RFC2068, unescape...
+                       s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
+               }
+
+               try {
+                       // Replace server-side written pluses with spaces.
+                       // If we can't decode the cookie, ignore it, it's unusable.
+                       s = decodeURIComponent(s.replace(pluses, ' '));
+               } catch(e) {
+                       return;
+               }
+
+               try {
+                       // If we can't parse the cookie, ignore it, it's unusable.
+                       return config.json ? JSON.parse(s) : s;
+               } catch(e) {}
+       }
+
+       function read(s, converter) {
+               var value = config.raw ? s : parseCookieValue(s);
+               return $.isFunction(converter) ? converter(value) : value;
+       }
+
+       var config = $.cookie = function (key, value, options) {
+
+               // Write
+               if (value !== undefined && !$.isFunction(value)) {
+                       options = $.extend({}, config.defaults, options);
+
+                       if (typeof options.expires === 'number') {
+                               var days = options.expires, t = options.expires = new Date();
+                               t.setDate(t.getDate() + days);
+                       }
+
+                       return (document.cookie = [
+                               encode(key), '=', stringifyCookieValue(value),
+                               options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
+                               options.path    ? '; path=' + options.path : '',
+                               options.domain  ? '; domain=' + options.domain : '',
+                               options.secure  ? '; secure' : ''
+                       ].join(''));
+               }
+
+               // Read
+
+               var result = key ? undefined : {};
+
+               // To prevent the for loop in the first place assign an empty array
+               // in case there are no cookies at all. Also prevents odd result when
+               // calling $.cookie().
+               var cookies = document.cookie ? document.cookie.split('; ') : [];
+
+               for (var i = 0, l = cookies.length; i < l; i++) {
+                       var parts = cookies[i].split('=');
+                       var name = decode(parts.shift());
+                       var cookie = parts.join('=');
+
+                       if (key && key === name) {
+                               // If second argument (value) is a function it's a converter...
+                               result = read(cookie, value);
+                               break;
+                       }
+
+                       // Prevent storing a cookie that we couldn't decode.
+                       if (!key && (cookie = read(cookie)) !== undefined) {
+                               result[name] = cookie;
+                       }
+               }
+
+               return result;
+       };
+
+       config.defaults = {};
+
+       $.removeCookie = function (key, options) {
+               if ($.cookie(key) !== undefined) {
+                       // Must not alter options, thus extending a fresh object...
+                       $.cookie(key, '', $.extend({}, options, { expires: -1 }));
+                       return true;
+               }
+               return false;
+       };
+
+}));
index a178320debb557b19a42061335c48d4a8f75b4a8..bcb82c31a5c2102181d2c07194220011c1e6a269 100644 (file)
@@ -150,7 +150,18 @@ $(function() {
 
   // Embed the converted markdown if it is on the page, else default to the iframe
   if ($('#note-markdown').length > 0) {
-    $('#note-markdown').html(marked($('#note-markdown').data('markdown')));
+    var note_markdown = $('#note-markdown');
+    note_markdown.html(marked(note_markdown.data('markdown')));
+    note_markdown.annotator();
+    note_markdown.annotator('addPlugin', 'Store', {
+      prefix: '/ajax/annotations',
+      loadFromSearch: {
+        'uri': note_id
+      },
+      annotationData: {
+        'uri': note_id
+      }
+    });
   } else {
     $.ajax(note_contents_url, {
       type: 'GET',
index 646caccf77bbbede9555238ebc3fceb6aae64745..70dccca7da91a86766ab8e7683ff5d46d968136a 100644 (file)
@@ -73,7 +73,6 @@ AWS_HEADERS = {
 ########## TOOLBAR CONFIGURATION
 # See: https://github.com/django-debug-toolbar/django-debug-toolbar#installation
 INSTALLED_APPS += (
-    'debug_toolbar',
     'django_extensions',
     'django_nose',
 )
@@ -83,7 +82,6 @@ INTERNAL_IPS = ('127.0.0.1',)
 
 # See: https://github.com/django-debug-toolbar/django-debug-toolbar#installation
 MIDDLEWARE_CLASSES += (
-    'debug_toolbar.middleware.DebugToolbarMiddleware',
 )
 
 
index fada1a7d140f85922803d466fd48c12fb3b4f04a..109b6a8d5607571224ff5069f426d299bbf341c8 100644 (file)
   {% include 'footer.html' %}
   <!-- end include footer-->
 
-  <!-- block bodyscripts -->
-  {% block bodyscripts %}
-  {% endblock %}
-  <!-- end block bodyscripts -->
   <script src="{{ STATIC_URL }}js/opentip-jquery-excanvas.min.js"></script>
   <script src="{{ STATIC_URL }}js/foundation.min.js"></script>
   <script>
-    $(document).foundation();
+    $(function() {
+      $(document).foundation();
+    });
   </script>
+  <!-- block bodyscripts -->
+  {% block bodyscripts %}
+  {% endblock %}
+  <!-- end block bodyscripts -->
 
 </body>
 </html>
index b1e10f3456437326397573d45b2e29b486b4d76a..1a8e31f19dd41db2568217c1b5fa9f3a342b2e08 100644 (file)
@@ -7,10 +7,12 @@
 
 {% block pagestyle %}
   <link rel="stylesheet" type="text/css" media="all" href="{{ STATIC_URL }}css/note_course_pages.css">
+  <link type="text/css" rel="stylesheet" href="{{ STATIC_URL }}css/annotator.min.css" />
 {% endblock %}
 
 {% block pagescripts %}
   <script type="text/javascript">
+    var note_id = {{ note.id }};
     var note_thank_url = "{% url 'thank_note' note.id %}"
     var note_flag_url = "{% url 'flag_note' note.id %}"
     var edit_note_tags_url = "{% url 'edit_note_tags' note.id %}"
   <script src="{{ STATIC_URL }}js/note-detail.js" ></script>
   <script src="{{ STATIC_URL }}js/pxem.jQuery.js"></script>
   <script src="{{ STATIC_URL }}js/marked.js" ></script>
+  <script src="{{ STATIC_URL }}js/annotator-full.min.js"></script>
+  <script src="{{ STATIC_URL }}js/jquery.cookie.js"></script>
+  <script>
+    $(function() {
+      $(document).foundation('joyride', 'start');
+    });
+  </script>
 {% endblock %}
 
 {% block raw_content %}
@@ -34,7 +43,7 @@
     <div class="return-to-course show-for-large-up">
       <div class="row">
         <div class="small-12 columns">
-          <a href="{{note.course.get_absolute_url}}">
+          <a href="{{ note.course.get_absolute_url }}">
             <i class="fa fa-angle-double-left"></i> See all notes for {{ note.course.name }}
           </a>
         </div>
 
   </section><!--/note_content-->
 
+  <ol class="joyride-list" data-joyride
+        data-options="cookie_monster: true; cookie_name: note_detail_joyride">
+    <li data-id="note-markdown" data-text="Awesome!" data-options="tip_location: top">
+      <p>You can highlight important words or phrases in this note to add definitions for them.</p>
+    </li>
+  </ol>
+
 {% endblock %}
 
 
index 49e35cf36465b64dedf3f2c9a3a664c92355bb4b..ff574699abc300a36767a380dd9d39f486d89a36 100644 (file)
@@ -35,7 +35,7 @@
     <div id="activity_container">
       <div class="row">
         <div id="tabs" class="small-12 columns">
-          <dl class="tabs show-for-large-up" data-tab data-options="deep_linking: true">
+          <dl class="tabs show-for-large-up" data-tab data-options="deep_linking: true; scroll_to_content: false;">
             <dd class="active"><a href="#activity">Karma Point Activity</a></dd>
             <dd><a href="#control_panel">My Account</a></dd>
           </dl>
index ccc7defe1b7b94e57d4852a9902bf98e9045d2f6..a58194b358d7c935a7521bc86fb907d37841aac9 100644 (file)
@@ -18,7 +18,8 @@ from karmaworld.apps.courses.views import school_course_instructor_list
 from karmaworld.apps.notes.views import NoteView, thank_note, NoteSearchView, flag_note, downloaded_note, edit_note_tags
 from karmaworld.apps.moderation import moderator
 from karmaworld.apps.document_upload.views import save_fp_upload
-from karmaworld.apps.quizzes.views import QuizView, KeywordEditView, quiz_answer
+from karmaworld.apps.quizzes.views import QuizView, KeywordEditView, quiz_answer, get_keywords, \
+    set_delete_keyword
 from karmaworld.apps.users.views import ProfileView
 
 # See: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#hooking-adminsite-instances-into-your-urlconf
@@ -104,6 +105,9 @@ urlpatterns = patterns('',
     # Check if a quiz answer is correct
     url(r'^ajax/quiz/check/$', quiz_answer, name='quiz_answer'),
 
+    url(r'^ajax/annotations/annotations$', set_delete_keyword, name='set_keyword'),
+    url(r'^ajax/annotations/search/$', get_keywords, name='get_keywords'),
+
     # Valid url cases to the Note page
     # a: school/course/id
     # b: school/course/id/slug
index e9c769da9b713b382f57afd40d18df2c54daeeb4..2395bc3713f609c1f1e492709baa8f8434e893d6 100644 (file)
@@ -1 +1 @@
-from ajax_increment import *
\ No newline at end of file
+from ajax_utils import *
\ No newline at end of file
diff --git a/karmaworld/utils/ajax_increment.py b/karmaworld/utils/ajax_increment.py
deleted file mode 100644 (file)
index f9e772f..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-import json
-from django.core.exceptions import ObjectDoesNotExist
-from django.http import HttpResponseBadRequest, HttpResponseNotFound, HttpResponse
-
-
-def format_session_increment_field(cls, id, field):
-    return cls.__name__ + '-' + field + '-' + str(id)
-
-
-def ajax_base(cls, request, pk, event_processor):
-    """Handle an AJAX request"""
-    if not (request.method == 'POST' and request.is_ajax()):
-        # return that the api call failed
-        return HttpResponseBadRequest(json.dumps({'status': 'fail', 'message': 'must be a POST ajax request'}),
-                                      mimetype="application/json")
-
-    try:
-        obj = cls.objects.get(pk=pk)
-        event_processor(request.user, obj)
-
-    except ObjectDoesNotExist:
-        return HttpResponseNotFound(json.dumps({'status': 'fail', 'message': 'id does not match a ' + cls.__name__}),
-                                    mimetype="application/json")
-
-    return HttpResponse(status=204)
-
-
-def ajax_increment(cls, request, pk, field, user_profile_field=None, event_processor=None):
-    def ajax_increment_work(request_user, obj):
-        count = getattr(obj, field)
-        setattr(obj, field,  count+1)
-        obj.save()
-
-        if event_processor:
-            event_processor(request.user, obj)
-
-        # Record that user has performed this, to prevent
-        # them from doing it again
-        if user_profile_field:
-            getattr(request_user.get_profile(), user_profile_field).add(obj)
-            obj.save()
-
-    return ajax_base(cls, request, pk, ajax_increment_work)
diff --git a/karmaworld/utils/ajax_utils.py b/karmaworld/utils/ajax_utils.py
new file mode 100644 (file)
index 0000000..220852c
--- /dev/null
@@ -0,0 +1,57 @@
+import json
+from django.core.exceptions import ObjectDoesNotExist
+from django.http import HttpResponseBadRequest, HttpResponseNotFound, HttpResponse
+
+
+def format_session_increment_field(cls, id, field):
+    return cls.__name__ + '-' + field + '-' + str(id)
+
+
+def ajax_base(request, event_processor, allowed_methods):
+    """Handle an AJAX request"""
+    if not request.method in allowed_methods or not request.is_ajax():
+        # return that the api call failed
+        return HttpResponseBadRequest(json.dumps({'status': 'fail', 'message': 'must be an ajax request with method ' + str(allowed_methods)}),
+                                      mimetype="application/json")
+
+    resp = event_processor(request)
+    if resp:
+        return resp
+    else:
+        return HttpResponse(status=204)
+
+
+def ajax_pk_base(cls, request, pk, event_processor):
+    """Handle an AJAX request"""
+    if not request.is_ajax():
+        # return that the api call failed
+        return HttpResponseBadRequest(json.dumps({'status': 'fail', 'message': 'must be a POST ajax request'}),
+                                      mimetype="application/json")
+
+    try:
+        obj = cls.objects.get(pk=pk)
+        event_processor(request.user, obj)
+
+    except ObjectDoesNotExist:
+        return HttpResponseNotFound(json.dumps({'status': 'fail', 'message': 'id does not match a ' + cls.__name__}),
+                                    mimetype="application/json")
+
+    return HttpResponse(status=204)
+
+
+def ajax_increment(cls, request, pk, field, user_profile_field=None, event_processor=None):
+    def ajax_increment_work(request_user, obj):
+        count = getattr(obj, field)
+        setattr(obj, field,  count+1)
+        obj.save()
+
+        if event_processor:
+            event_processor(request.user, obj)
+
+        # Record that user has performed this, to prevent
+        # them from doing it again
+        if user_profile_field:
+            getattr(request_user.get_profile(), user_profile_field).add(obj)
+            obj.save()
+
+    return ajax_pk_base(cls, request, pk, ajax_increment_work)