From 5c8b9cd38e7008c1350c02b4b2defda9494e5e81 Mon Sep 17 00:00:00 2001 From: daniel cebrian Date: Thu, 16 Jan 2014 01:03:46 +0100 Subject: [PATCH 01/61] annotation tools --- cms/envs/common.py | 31 +- cms/urls.py | 3 + .../student/firebase_token_generator.py | 50 + common/djangoapps/student/views.py | 21 + common/lib/xmodule/setup.py | 2 + .../xmodule/modulestore/inheritance.py | 1 + .../xmodule/tests/testtextannotation.py | 58 + .../xmodule/tests/testvideoannotation.py | 131 + .../xmodule/tests/videoannotation_module.py | 167 + .../xmodule/xmodule/textannotation_module.py | 104 + .../xmodule/xmodule/videoannotation_module.py | 164 + common/static/css/vendor/f/1/vjs.eot | Bin 0 -> 3536 bytes common/static/css/vendor/f/1/vjs.svg | 65 + common/static/css/vendor/f/1/vjs.ttf | Bin 0 -> 3372 bytes common/static/css/vendor/f/1/vjs.woff | Bin 0 -> 4228 bytes common/static/css/vendor/ova/annotator.css | 888 +++ .../static/css/vendor/ova/edx-annotator.css | 101 + .../css/vendor/ova/flagging-annotator.css | 27 + common/static/css/vendor/ova/ova.css | 605 ++ common/static/css/vendor/ova/rangeslider.css | 186 + .../css/vendor/ova/richText-annotator.css | 33 + .../static/css/vendor/ova/share-annotator.css | 203 + .../static/css/vendor/ova/tags-annotator.css | 97 + .../css/vendor/ova/video-js.font.dev.svg | 65 + common/static/css/vendor/ova/video-js.fw.png | Bin 0 -> 78899 bytes common/static/css/vendor/ova/video-js.less | 949 +++ common/static/css/vendor/ova/video-js.min.css | 5 + common/static/css/vendor/ova/video-js.png | Bin 0 -> 4565 bytes lms/djangoapps/notes/api.py | 10 + lms/djangoapps/notes/urls.py | 3 +- lms/djangoapps/notes/views.py | 13 +- lms/djangoapps/staticbook/views.py | 8 + lms/envs/common.py | 30 +- lms/static/coffee/src/notes.coffee | 78 +- lms/static/js/vendor/ova/annotator-full.js | 3386 +++++++++ lms/static/js/vendor/ova/catch/css/main.css | 516 ++ .../js/vendor/ova/catch/img/closeIcon.png | Bin 0 -> 1114 bytes .../vendor/ova/catch/img/expandableIcon.png | Bin 0 -> 1279 bytes .../ova/catch/img/expandableIcon_Arrow.png | Bin 0 -> 3002 bytes lms/static/js/vendor/ova/catch/img/fish.jpg | Bin 0 -> 11572 bytes .../vendor/ova/catch/img/geolocation_icon.png | Bin 0 -> 740 bytes .../js/vendor/ova/catch/img/groups_icon.png | Bin 0 -> 747 bytes .../js/vendor/ova/catch/img/privacy_icon.png | Bin 0 -> 635 bytes .../js/vendor/ova/catch/img/shareControls.png | Bin 0 -> 9691 bytes .../js/vendor/ova/catch/img/share_icon.png | Bin 0 -> 655 bytes lms/static/js/vendor/ova/catch/js/catch.js | 1107 +++ .../vendor/ova/catch/js/handlebars-1.1.2.js | 2595 +++++++ .../js/vendor/ova/flagging-annotator.js | 104 + lms/static/js/vendor/ova/jquery-Watch.js | 116 + lms/static/js/vendor/ova/ova.js | 2534 +++++++ lms/static/js/vendor/ova/rangeslider.js | 1059 +++ lms/static/js/vendor/ova/reply-annotator.js | 80 + .../js/vendor/ova/richText-annotator.js | 123 + lms/static/js/vendor/ova/share-annotator.js | 480 ++ .../skins/lightgray/content.inline.min.css | 1 + .../ova/skins/lightgray/content.min.css | 1 + .../skins/lightgray/fonts/icomoon-small.eot | Bin 0 -> 8344 bytes .../skins/lightgray/fonts/icomoon-small.svg | 175 + .../skins/lightgray/fonts/icomoon-small.ttf | Bin 0 -> 8160 bytes .../skins/lightgray/fonts/icomoon-small.woff | Bin 0 -> 8336 bytes .../ova/skins/lightgray/fonts/icomoon.eot | Bin 0 -> 8268 bytes .../ova/skins/lightgray/fonts/icomoon.svg | 153 + .../ova/skins/lightgray/fonts/icomoon.ttf | Bin 0 -> 8104 bytes .../ova/skins/lightgray/fonts/icomoon.woff | Bin 0 -> 8400 bytes .../vendor/ova/skins/lightgray/img/anchor.gif | Bin 0 -> 53 bytes .../vendor/ova/skins/lightgray/img/loader.gif | Bin 0 -> 2608 bytes .../vendor/ova/skins/lightgray/img/object.gif | Bin 0 -> 152 bytes .../vendor/ova/skins/lightgray/img/trans.gif | Bin 0 -> 43 bytes .../vendor/ova/skins/lightgray/img/wline.gif | Bin 0 -> 46 bytes .../ova/skins/lightgray/skin.ie7.min.css | 1 + .../vendor/ova/skins/lightgray/skin.min.css | 1 + lms/static/js/vendor/ova/tags-annotator.js | 1100 +++ lms/static/js/vendor/ova/tinymce.min.js | 9 + lms/static/js/vendor/ova/video.dev.js | 6461 +++++++++++++++++ lms/static/js/vendor/ova/vjs.youtube.js | 605 ++ lms/templates/notes.html | 150 +- lms/templates/static_htmlbook.html | 3 +- lms/templates/textannotation.html | 187 + lms/templates/videoannotation.html | 191 + lms/urls.py | 1 + 80 files changed, 25196 insertions(+), 41 deletions(-) create mode 100644 common/djangoapps/student/firebase_token_generator.py create mode 100644 common/lib/xmodule/xmodule/tests/testtextannotation.py create mode 100644 common/lib/xmodule/xmodule/tests/testvideoannotation.py create mode 100644 common/lib/xmodule/xmodule/tests/videoannotation_module.py create mode 100644 common/lib/xmodule/xmodule/textannotation_module.py create mode 100644 common/lib/xmodule/xmodule/videoannotation_module.py create mode 100644 common/static/css/vendor/f/1/vjs.eot create mode 100644 common/static/css/vendor/f/1/vjs.svg create mode 100644 common/static/css/vendor/f/1/vjs.ttf create mode 100644 common/static/css/vendor/f/1/vjs.woff create mode 100644 common/static/css/vendor/ova/annotator.css create mode 100644 common/static/css/vendor/ova/edx-annotator.css create mode 100644 common/static/css/vendor/ova/flagging-annotator.css create mode 100644 common/static/css/vendor/ova/ova.css create mode 100644 common/static/css/vendor/ova/rangeslider.css create mode 100644 common/static/css/vendor/ova/richText-annotator.css create mode 100644 common/static/css/vendor/ova/share-annotator.css create mode 100644 common/static/css/vendor/ova/tags-annotator.css create mode 100644 common/static/css/vendor/ova/video-js.font.dev.svg create mode 100644 common/static/css/vendor/ova/video-js.fw.png create mode 100644 common/static/css/vendor/ova/video-js.less create mode 100644 common/static/css/vendor/ova/video-js.min.css create mode 100644 common/static/css/vendor/ova/video-js.png create mode 100644 lms/static/js/vendor/ova/annotator-full.js create mode 100644 lms/static/js/vendor/ova/catch/css/main.css create mode 100644 lms/static/js/vendor/ova/catch/img/closeIcon.png create mode 100644 lms/static/js/vendor/ova/catch/img/expandableIcon.png create mode 100644 lms/static/js/vendor/ova/catch/img/expandableIcon_Arrow.png create mode 100644 lms/static/js/vendor/ova/catch/img/fish.jpg create mode 100644 lms/static/js/vendor/ova/catch/img/geolocation_icon.png create mode 100644 lms/static/js/vendor/ova/catch/img/groups_icon.png create mode 100644 lms/static/js/vendor/ova/catch/img/privacy_icon.png create mode 100644 lms/static/js/vendor/ova/catch/img/shareControls.png create mode 100644 lms/static/js/vendor/ova/catch/img/share_icon.png create mode 100644 lms/static/js/vendor/ova/catch/js/catch.js create mode 100644 lms/static/js/vendor/ova/catch/js/handlebars-1.1.2.js create mode 100644 lms/static/js/vendor/ova/flagging-annotator.js create mode 100644 lms/static/js/vendor/ova/jquery-Watch.js create mode 100644 lms/static/js/vendor/ova/ova.js create mode 100644 lms/static/js/vendor/ova/rangeslider.js create mode 100644 lms/static/js/vendor/ova/reply-annotator.js create mode 100644 lms/static/js/vendor/ova/richText-annotator.js create mode 100644 lms/static/js/vendor/ova/share-annotator.js create mode 100644 lms/static/js/vendor/ova/skins/lightgray/content.inline.min.css create mode 100644 lms/static/js/vendor/ova/skins/lightgray/content.min.css create mode 100644 lms/static/js/vendor/ova/skins/lightgray/fonts/icomoon-small.eot create mode 100644 lms/static/js/vendor/ova/skins/lightgray/fonts/icomoon-small.svg create mode 100644 lms/static/js/vendor/ova/skins/lightgray/fonts/icomoon-small.ttf create mode 100644 lms/static/js/vendor/ova/skins/lightgray/fonts/icomoon-small.woff create mode 100644 lms/static/js/vendor/ova/skins/lightgray/fonts/icomoon.eot create mode 100644 lms/static/js/vendor/ova/skins/lightgray/fonts/icomoon.svg create mode 100644 lms/static/js/vendor/ova/skins/lightgray/fonts/icomoon.ttf create mode 100644 lms/static/js/vendor/ova/skins/lightgray/fonts/icomoon.woff create mode 100644 lms/static/js/vendor/ova/skins/lightgray/img/anchor.gif create mode 100644 lms/static/js/vendor/ova/skins/lightgray/img/loader.gif create mode 100644 lms/static/js/vendor/ova/skins/lightgray/img/object.gif create mode 100644 lms/static/js/vendor/ova/skins/lightgray/img/trans.gif create mode 100644 lms/static/js/vendor/ova/skins/lightgray/img/wline.gif create mode 100644 lms/static/js/vendor/ova/skins/lightgray/skin.ie7.min.css create mode 100644 lms/static/js/vendor/ova/skins/lightgray/skin.min.css create mode 100644 lms/static/js/vendor/ova/tags-annotator.js create mode 100644 lms/static/js/vendor/ova/tinymce.min.js create mode 100644 lms/static/js/vendor/ova/video.dev.js create mode 100644 lms/static/js/vendor/ova/vjs.youtube.js create mode 100644 lms/templates/textannotation.html create mode 100644 lms/templates/videoannotation.html diff --git a/cms/envs/common.py b/cms/envs/common.py index c96b17195910..1ac0a7f562cb 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -65,7 +65,7 @@ # If set to True, Studio won't restrict the set of advanced components # to just those pre-approved by edX - 'ALLOW_ALL_ADVANCED_COMPONENTS': False, + 'ALLOW_ALL_ADVANCED_COMPONENTS': True, } ENABLE_JASMINE = False @@ -272,6 +272,16 @@ 'css/vendor/jquery.qtip.min.css', 'js/vendor/markitup/skins/simple/style.css', 'js/vendor/markitup/sets/wiki/style.css', + 'css/vendor/ova/edx-annotator.css', + 'css/vendor/ova/annotator.css', + 'css/vendor/ova/video-js.min.css', + 'css/vendor/ova/rangeslider.css', + 'css/vendor/ova/share-annotator.css', + 'css/vendor/ova/richText-annotator.css', + 'css/vendor/ova/tags-annotator.css', + 'css/vendor/ova/flagging-annotator.css', + 'css/vendor/ova/ova.css', + 'js/vendor/ova/catch/css/main.css' ], 'output_filename': 'css/cms-style-vendor.css', }, @@ -307,6 +317,25 @@ 'output_filename': 'js/cms-modules.js', 'test_order': 1 }, + 'main_vendor': { + 'source_filenames': [ + 'js/vendor/ova/annotator-full.js', + 'js/vendor/ova/video.dev.js', + 'js/vendor/ova/vjs.youtube.js', + 'js/vendor/ova/rangeslider.js', + 'js/vendor/ova/share-annotator.js', + 'js/vendor/ova/tinymce.min.js', + 'js/vendor/ova/richText-annotator.js', + 'js/vendor/ova/reply-annotator.js', + 'js/vendor/ova/tags-annotator.js', + 'js/vendor/ova/flagging-annotator.js', + 'js/vendor/ova/jquery-Watch.js', + 'js/vendor/ova/ova.js', + 'js/vendor/ova/catch/js/catch.js', + 'js/vendor/ova/catch/js/handlebars-1.1.2.js' + ], + 'output_filename': 'js/cms-main_vendor.js', + }, } PIPELINE_COMPILERS = ( diff --git a/cms/urls.py b/cms/urls.py index 8b6b18ef71bf..dac22f836b96 100644 --- a/cms/urls.py +++ b/cms/urls.py @@ -48,6 +48,9 @@ # ajax view that actually does the work url(r'^login_post$', 'student.views.login_user', name='login_post'), url(r'^logout$', 'student.views.logout_user', name='logout'), + + #added token + url(r'^token/', 'student.views.token', name="token"), ) # restful api diff --git a/common/djangoapps/student/firebase_token_generator.py b/common/djangoapps/student/firebase_token_generator.py new file mode 100644 index 000000000000..30ab9295019a --- /dev/null +++ b/common/djangoapps/student/firebase_token_generator.py @@ -0,0 +1,50 @@ +from array import array +from base64 import urlsafe_b64encode +import hashlib +import hmac +import sys +try: + import json +except ImportError: + import simplejson as json +import time +import datetime + +__all__ = ['create_token'] + +TOKEN_SEP = '.' + +def create_token(secret, data): + claims = data + + return _encode_token(secret, claims) + + +if sys.version_info < (2, 7): + def _encode(bytes_data): + # Python 2.6 has problems with bytearrays in b64 + encoded = urlsafe_b64encode(bytes(bytes_data)) + return encoded.decode('utf-8').replace('=', '') +else: + def _encode(bytes): + encoded = urlsafe_b64encode(bytes) + return encoded.decode('utf-8').replace('=', '') + + +def _encode_json(obj): + return _encode(bytearray(json.dumps(obj), 'utf-8')) + +def _sign(secret, to_sign): + def portable_bytes(s): + try: + return bytes(s, 'utf-8') + except TypeError: + return bytes(s) + return _encode(hmac.new(portable_bytes(secret), portable_bytes(to_sign), hashlib.sha256).digest()) + +def _encode_token(secret, claims): + encoded_header = _encode_json({'typ': 'JWT', 'alg': 'HS256'}) + encoded_claims = _encode_json(claims) + secure_bits = '%s%s%s' % (encoded_header, TOKEN_SEP, encoded_claims) + sig = _sign(secret, secure_bits) + return '%s%s%s' % (secure_bits, TOKEN_SEP, sig) diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index cae7605f28ef..52fde394dc3d 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -1443,3 +1443,24 @@ def change_email_settings(request): track.views.server_track(request, "change-email-settings", {"receive_emails": "no", "course": course_id}, page='dashboard') return HttpResponse(json.dumps({'success': True})) + +from student.firebase_token_generator import create_token + + +@login_required +def token(request): + ''' + Return a token for the backend of annotations + ''' + secret = request + dtnow = datetime.datetime.now() + dtutcnow = datetime.datetime.utcnow() + delta = dtnow - dtutcnow + newhour, newmin = divmod((delta.days * 24 * 60 * 60 + delta.seconds + 30) // 60, 60) + newtime = "%s%+02d:%02d" % (dtnow.isoformat(), newhour, newmin) + secret = '4c7f4d1c-8ac4-4e9f-84c8-b271c57fcac4' + custom_data = {"issuedAt": newtime, "consumerKey": "4c7f4d1c-8ac4-4e9f-84c8-b271c57fcac4", "userId": "username", "ttl": 86400} + newtoken = create_token(secret, custom_data) + response = HttpResponse(newtoken, mimetype="text/plain") + + return response diff --git a/common/lib/xmodule/setup.py b/common/lib/xmodule/setup.py index 558668c9fae8..f487081f8fc9 100644 --- a/common/lib/xmodule/setup.py +++ b/common/lib/xmodule/setup.py @@ -33,6 +33,8 @@ "wrapper = xmodule.wrapper_module:WrapperDescriptor", "graphical_slider_tool = xmodule.gst_module:GraphicalSliderToolDescriptor", "annotatable = xmodule.annotatable_module:AnnotatableDescriptor", + "textannotation = xmodule.textannotation_module:TextAnnotationDescriptor", + "videoannotation = xmodule.videoannotation_module:VideoAnnotationDescriptor", "foldit = xmodule.foldit_module:FolditDescriptor", "word_cloud = xmodule.word_cloud_module:WordCloudDescriptor", "hidden = xmodule.hidden_module:HiddenDescriptor", diff --git a/common/lib/xmodule/xmodule/modulestore/inheritance.py b/common/lib/xmodule/xmodule/modulestore/inheritance.py index 8f824f38c668..308206b107e0 100644 --- a/common/lib/xmodule/xmodule/modulestore/inheritance.py +++ b/common/lib/xmodule/xmodule/modulestore/inheritance.py @@ -41,6 +41,7 @@ class InheritanceMixin(XBlockMixin): scope=Scope.settings, ) xqa_key = String(help="DO NOT USE", scope=Scope.settings) + annotation_storage_url = String(help="Location of Annotation backend", scope=Scope.settings, default="http://your_annotation_storage.com", display_name="annotation_storage_url") graceperiod = Timedelta( help="Amount of time after the due date that submissions will be accepted", scope=Scope.settings, diff --git a/common/lib/xmodule/xmodule/tests/testtextannotation.py b/common/lib/xmodule/xmodule/tests/testtextannotation.py new file mode 100644 index 000000000000..105f968ae2b5 --- /dev/null +++ b/common/lib/xmodule/xmodule/tests/testtextannotation.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +"Test for Annotation Xmodule functional logic." + +import unittest +from mock import Mock +from lxml import etree + +from xblock.field_data import DictFieldData +from xblock.fields import ScopeIds + +from xmodule.textannotation_module import TextAnnotationModule +from xmodule.modulestore import Location + +from . import get_test_system + +class TextAnnotationModuleTestCase(unittest.TestCase): + sample_xml = ''' + +

Test Instructions.

+

+ One Fish. Two Fish. + Red Fish. Blue Fish. + + Oh the places you'll go! +

+
+ ''' + def setUp(self): + self.mod = TextAnnotationModule( + Mock(), + get_test_system(), + DictFieldData({'data':self.sample_xml}), + ScopeIds(None, None, None, None) + ) + + def test_render_content(self): + content = self.mod._render_content() + self.assertIsNotNone(content) + el = etree.fromstring(content) + self.assertIsNotNone(el) + self.assertFalse('display_name' in el.attrib, "Display Name should have been deleted from Content") + + def test_extract_instructions(self): + xmltree = etree.fromstring(self.sample_xml) + + expected_xml = u"

Test Instructions.

" + actual_xml = self.mod._extract_instructions(xmltree) + self.assertIsNotNone(actual_xml) + self.assertEqual(expected_xml.strip(), actual_xml.strip()) + + xmltree = etree.fromstring('foo') + actual = self.mod._extract_instructions(xmltree) + self.assertIsNone(actual) + + def test_get_html(self): + context = self.mod.get_html() + for key in ['display_name', 'tag','source','element_id','instructions_html','content_html','annotation_storage']: + self.assertIn(key, context) \ No newline at end of file diff --git a/common/lib/xmodule/xmodule/tests/testvideoannotation.py b/common/lib/xmodule/xmodule/tests/testvideoannotation.py new file mode 100644 index 000000000000..528245071fc4 --- /dev/null +++ b/common/lib/xmodule/xmodule/tests/testvideoannotation.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- +"Test for Annotation Xmodule functional logic." + +import unittest +from mock import Mock +from lxml import etree + +from xblock.field_data import DictFieldData +from xblock.fields import ScopeIds + +from xmodule.textannotation_module import VideoAnnotationModule +from xmodule.modulestore import Location + +from . import get_test_system + +class VideoAnnotationModuleTestCase(unittest.TestCase): + sample_xml = ''' + +

Video Test Instructions.

+
+ ''' + sample_sourceURL = "http://video-js.zencoder.com/oceans-clip.mp4" + sample_youtubeURL = "http://www.youtube.com/watch?v=yxLIu-scR9Y" + + def setUp(self): + self.mod = VideoAnnotationModule( + Mock(), + get_test_system(), + DictFieldData({'data':self.sample_xml, 'sourceUrl':sample_sourceURL}), + ScopeIds(None, None, None, None) + ) + + def test_annotation_class_attr_default(self): + xml = 'test' + el = etree.fromstring(xml) + + expected_attr = { 'class': { 'value': 'annotatable-span highlight' } } + actual_attr = self.mod._get_annotation_class_attr(0, el) + + self.assertIsInstance(actual_attr, dict) + self.assertDictEqual(expected_attr, actual_attr) + + def test_annotation_class_attr_with_valid_highlight(self): + xml = 'test' + + for color in self.mod.highlight_colors: + el = etree.fromstring(xml.format(highlight=color)) + value = 'annotatable-span highlight highlight-{highlight}'.format(highlight=color) + + expected_attr = { 'class': { + 'value': value, + '_delete': 'highlight' } + } + actual_attr = self.mod._get_annotation_class_attr(0, el) + + self.assertIsInstance(actual_attr, dict) + self.assertDictEqual(expected_attr, actual_attr) + + def test_annotation_class_attr_with_invalid_highlight(self): + xml = 'test' + + for invalid_color in ['rainbow', 'blink', 'invisible', '', None]: + el = etree.fromstring(xml.format(highlight=invalid_color)) + expected_attr = { 'class': { + 'value': 'annotatable-span highlight', + '_delete': 'highlight' } + } + actual_attr = self.mod._get_annotation_class_attr(0, el) + + self.assertIsInstance(actual_attr, dict) + self.assertDictEqual(expected_attr, actual_attr) + + def test_annotation_data_attr(self): + el = etree.fromstring('test') + + expected_attr = { + 'data-comment-body': {'value': 'foo', '_delete': 'body' }, + 'data-comment-title': {'value': 'bar', '_delete': 'title'}, + 'data-problem-id': {'value': '0', '_delete': 'problem'} + } + + actual_attr = self.mod._get_annotation_data_attr(0, el) + + self.assertIsInstance(actual_attr, dict) + self.assertDictEqual(expected_attr, actual_attr) + + def test_render_annotation(self): + expected_html = 'z' + expected_el = etree.fromstring(expected_html) + + actual_el = etree.fromstring('z') + self.mod._render_annotation(0, actual_el) + + self.assertEqual(expected_el.tag, actual_el.tag) + self.assertEqual(expected_el.text, actual_el.text) + self.assertDictEqual(dict(expected_el.attrib), dict(actual_el.attrib)) + + def test_render_content(self): + content = self.mod._render_content() + el = etree.fromstring(content) + + self.assertEqual('div', el.tag, 'root tag is a div') + + expected_num_annotations = 5 + actual_num_annotations = el.xpath('count(//span[contains(@class,"annotatable-span")])') + self.assertEqual(expected_num_annotations, actual_num_annotations, 'check number of annotations') + + def test_extract_instructions(self): + xmltree = etree.fromstring(self.sample_xml) + + expected_xml = u"
Read the text.
" + actual_xml = self.mod._extract_instructions(xmltree) + self.assertIsNotNone(actual_xml) + self.assertEqual(expected_xml.strip(), actual_xml.strip()) + + xmltree = etree.fromstring('foo') + actual = self.mod._extract_instructions(xmltree) + self.assertIsNone(actual) + + def test_get_extension(self): + expectedYoutube = 'video/youtube' + expectedNotYoutube = 'video/mp4' + result1 = self.mod._get_extension(sample_sourceURL) + result2 = self.mod._get_extension(sample_youtubeURL) + self.assertEqual(expectedYoutube, result2) + self.assertEqual(expectedNotYoutube, result1) + + def test_get_html(self): + context = self.mod.get_html() + for key in ['display_name', 'element_id', 'content_html', 'instructions_html', 'sourceUrl','typeSource','poster','alert','annotation_storage']: + self.assertIn(key, context) \ No newline at end of file diff --git a/common/lib/xmodule/xmodule/tests/videoannotation_module.py b/common/lib/xmodule/xmodule/tests/videoannotation_module.py new file mode 100644 index 000000000000..f9b22611ef62 --- /dev/null +++ b/common/lib/xmodule/xmodule/tests/videoannotation_module.py @@ -0,0 +1,167 @@ +import logging + +from lxml import etree +from pkg_resources import resource_string + +from xmodule.x_module import XModule +from xmodule.raw_module import RawDescriptor +from xblock.core import Scope, String + +import textwrap +from mimetypes import guess_type, guess_extension + +log = logging.getLogger(__name__) + +class AnnotatableFields(object): + """Fields for `VideoModule` and `VideoDescriptor`.""" + data = String(help="XML data for the annotation", scope=Scope.content, + default=textwrap.dedent( + """\ + + +

+ Add the instructions to the assignment here. +

+
+
+ """)) + display_name = String( + display_name="Display Name", + help="Display name for this module", + scope=Scope.settings, + default='Video Annotation', + ) + sourceUrl = String(help="The external source URL for the video.", display_name="Source URL", scope=Scope.settings, default="http://video-js.zencoder.com/oceans-clip.mp4") + poster_url = String(help="Poster Image URL", display_name="Poster URL", scope=Scope.settings, default="") + +class VideoAnnotationModule(AnnotatableFields, XModule): + js = {'coffee': [resource_string(__name__, 'js/src/javascript_loader.coffee'), + resource_string(__name__, 'js/src/collapsible.coffee'), + resource_string(__name__, 'js/src/html/display.coffee'), + resource_string(__name__, 'js/src/annotatable/display.coffee')], + 'js': [] + } +# js_module_name = "VideoAnnotation" + css = {'scss': [resource_string(__name__, 'css/annotatable/display.scss')]} + icon_class = 'videoannotation' + + def __init__(self, *args, **kwargs): + XModule.__init__(self, *args, **kwargs) + + xmltree = etree.fromstring(self.data) + + self.instructions = self._extract_instructions(xmltree) + self.content = etree.tostring(xmltree, encoding='unicode') + self.element_id = self.location.html_id() + self.highlight_colors = ['yellow', 'orange', 'purple', 'blue', 'green'] + + def _get_annotation_class_attr(self, index, el): + """ Returns a dict with the CSS class attribute to set on the annotation + and an XML key to delete from the element. + """ + + attr = {} + cls = ['annotatable-span', 'highlight'] + highlight_key = 'highlight' + color = el.get(highlight_key) + + if color is not None: + if color in self.highlight_colors: + cls.append('highlight-' + color) + attr['_delete'] = highlight_key + attr['value'] = ' '.join(cls) + + return {'class': attr} + + def _get_annotation_data_attr(self, index, el): + """ Returns a dict in which the keys are the HTML data attributes + to set on the annotation element. Each data attribute has a + corresponding 'value' and (optional) '_delete' key to specify + an XML attribute to delete. + """ + + data_attrs = {} + attrs_map = { + 'body': 'data-comment-body', + 'title': 'data-comment-title', + 'problem': 'data-problem-id' + } + + for xml_key in attrs_map.keys(): + if xml_key in el.attrib: + value = el.get(xml_key, '') + html_key = attrs_map[xml_key] + data_attrs[html_key] = {'value': value, '_delete': xml_key} + + return data_attrs + + def _render_annotation(self, index, el): + """ Renders an annotation element for HTML output. """ + attr = {} + attr.update(self._get_annotation_class_attr(index, el)) + attr.update(self._get_annotation_data_attr(index, el)) + + el.tag = 'span' + + for key in attr.keys(): + el.set(key, attr[key]['value']) + if '_delete' in attr[key] and attr[key]['_delete'] is not None: + delete_key = attr[key]['_delete'] + del el.attrib[delete_key] + + def _render_content(self): + """ Renders annotatable content with annotation spans and returns HTML. """ + xmltree = etree.fromstring(self.content) + xmltree.tag = 'div' + if 'display_name' in xmltree.attrib: + del xmltree.attrib['display_name'] + + index = 0 + for el in xmltree.findall('.//annotation'): + self._render_annotation(index, el) + index += 1 + + return etree.tostring(xmltree, encoding='unicode') + + def _extract_instructions(self, xmltree): + """ Removes from the xmltree and returns them as a string, otherwise None. """ + instructions = xmltree.find('instructions') + if instructions is not None: + instructions.tag = 'div' + xmltree.remove(instructions) + return etree.tostring(instructions, encoding='unicode') + return None + + def _get_extension(self,srcURL): + if 'youtu' in self.sourceUrl: + return 'video/youtube' + else: + spliturl = self.sourceUrl.split(".") + extensionPlus1 = spliturl[len(spliturl)-1] + spliturl = extensionPlus1.split("?") + extensionPlus2 = spliturl[0] + spliturl = extensionPlus2.split("#") + return 'video/' + spliturl[0] + + def get_html(self): + """ Renders parameters to template. """ + extension = self._get_extension(self.sourceUrl) + + context = { + 'display_name': self.display_name_with_default, + 'element_id': self.element_id, + 'instructions_html': self.instructions, + 'sourceUrl': self.sourceUrl, + 'typeSource': extension, + 'poster': self.poster_url, + 'alert': self, + 'content_html': self._render_content(), + 'annotation_storage':self.annotation_storage_url + } + + return self.system.render_template('videoannotation.html', context) + + +class VideoAnnotationDescriptor(AnnotatableFields, RawDescriptor): + module_class = VideoAnnotationModule + mako_template = "widgets/raw-edit.html" diff --git a/common/lib/xmodule/xmodule/textannotation_module.py b/common/lib/xmodule/xmodule/textannotation_module.py new file mode 100644 index 000000000000..da2d947952dd --- /dev/null +++ b/common/lib/xmodule/xmodule/textannotation_module.py @@ -0,0 +1,104 @@ +import logging + +from lxml import etree +from pkg_resources import resource_string + +from xmodule.x_module import XModule +from xmodule.raw_module import RawDescriptor +from xblock.core import Scope, String + +from django.conf import settings + +import textwrap +import xmodule.x_module + +log = logging.getLogger(__name__) + +class AnnotatableFields(object): + """Fields for `TextModule` and `TextDescriptor`.""" + data = String(help="XML data for the annotation", scope=Scope.content, + default=textwrap.dedent( + """\ + + +

+ Add the instructions to the assignment here. +

+
+

+ Lorem ipsum dolor sit amet, at amet animal petentium nec. Id augue nemore postulant mea. Ex eam dicant noluisse expetenda, alia admodum abhorreant qui et. An ceteros expetenda mea, tale natum ipsum quo no, ut pro paulo alienum noluisse. +

+
+ """)) + display_name = String( + display_name="Display Name", + help="Display name for this module", + scope=Scope.settings, + default='Text Annotation', + ) + tags = String( + display_name="Tags for Assignments", + help="Add tags that automatically highlight in a certain color using the comma-separated form, i.e. imagery:red,parallelism:blue", + scope=Scope.settings, + default='imagery:red,parallelism:blue', + ) + source = String( + display_name="Source/Citation", + help="Optional for citing source of any material used. Automatic citation can be done using EasyBib", + scope=Scope.settings, + default='None', + ) + +class TextAnnotationModule(AnnotatableFields, XModule): + js = {'coffee': [], + 'js': [] + } + css = {'scss': [resource_string(__name__, 'css/annotatable/display.scss')]} + icon_class = 'textannotation' + + def __init__(self, *args, **kwargs): + XModule.__init__(self, *args, **kwargs) + + xmltree = etree.fromstring(self.data) + + self.instructions = self._extract_instructions(xmltree) + self.content = etree.tostring(xmltree, encoding='unicode') + self.element_id = self.location.name + self.highlight_colors = ['yellow', 'orange', 'purple', 'blue', 'green'] + + + def _render_content(self): + """ Renders annotatable content with annotation spans and returns HTML. """ + xmltree = etree.fromstring(self.content) + if 'display_name' in xmltree.attrib: + del xmltree.attrib['display_name'] + + return etree.tostring(xmltree, encoding='unicode') + + def _extract_instructions(self, xmltree): + """ Removes from the xmltree and returns them as a string, otherwise None. """ + instructions = xmltree.find('instructions') + if instructions is not None: + instructions.tag = 'div' + xmltree.remove(instructions) + return etree.tostring(instructions, encoding='unicode') + return None + + def get_html(self): + """ Renders parameters to template. """ + context = { + 'display_name': self.display_name_with_default, + 'tag': self.tags, + 'source':self.source, + 'element_id': self.element_id, + 'instructions_html': self.instructions, + 'content_html': self._render_content(), + 'annotation_storage':self.annotation_storage_url + } + + return self.system.render_template('textannotation.html', context) + + +class TextAnnotationDescriptor(AnnotatableFields, RawDescriptor): + module_class = TextAnnotationModule + mako_template = "widgets/raw-edit.html" diff --git a/common/lib/xmodule/xmodule/videoannotation_module.py b/common/lib/xmodule/xmodule/videoannotation_module.py new file mode 100644 index 000000000000..95ca6319b185 --- /dev/null +++ b/common/lib/xmodule/xmodule/videoannotation_module.py @@ -0,0 +1,164 @@ +import logging + +from lxml import etree +from pkg_resources import resource_string + +from xmodule.x_module import XModule +from xmodule.raw_module import RawDescriptor +from xblock.core import Scope, String + +import textwrap +from mimetypes import guess_type, guess_extension + +log = logging.getLogger(__name__) + +class AnnotatableFields(object): + """Fields for `VideoModule` and `VideoDescriptor`.""" + data = String(help="XML data for the annotation", scope=Scope.content, + default=textwrap.dedent( + """\ + + +

+ Add the instructions to the assignment here. +

+
+
+ """)) + display_name = String( + display_name="Display Name", + help="Display name for this module", + scope=Scope.settings, + default='Video Annotation', + ) + sourceUrl = String(help="The external source URL for the video.", display_name="Source URL", scope=Scope.settings, default="http://video-js.zencoder.com/oceans-clip.mp4") + poster_url = String(help="Poster Image URL", display_name="Poster URL", scope=Scope.settings, default="") + +class VideoAnnotationModule(AnnotatableFields, XModule): + js = {'coffee': [resource_string(__name__, 'js/src/javascript_loader.coffee'), + resource_string(__name__, 'js/src/collapsible.coffee'), + resource_string(__name__, 'js/src/html/display.coffee'), + resource_string(__name__, 'js/src/annotatable/display.coffee')], + 'js': [] + } + css = {'scss': [resource_string(__name__, 'css/annotatable/display.scss')]} + icon_class = 'videoannotation' + + def __init__(self, *args, **kwargs): + XModule.__init__(self, *args, **kwargs) + + xmltree = etree.fromstring(self.data) + + self.instructions = self._extract_instructions(xmltree) + self.content = etree.tostring(xmltree, encoding='unicode') + self.element_id = self.location.html_id() + self.highlight_colors = ['yellow', 'orange', 'purple', 'blue', 'green'] + + def _get_annotation_class_attr(self, index, el): + """ Returns a dict with the CSS class attribute to set on the annotation + and an XML key to delete from the element. + """ + + attr = {} + cls = ['annotatable-span', 'highlight'] + highlight_key = 'highlight' + color = el.get(highlight_key) + + if color is not None: + if color in self.highlight_colors: + cls.append('highlight-' + color) + attr['_delete'] = highlight_key + attr['value'] = ' '.join(cls) + + return {'class': attr} + + def _get_annotation_data_attr(self, index, el): + """ Returns a dict in which the keys are the HTML data attributes + to set on the annotation element. Each data attribute has a + corresponding 'value' and (optional) '_delete' key to specify + an XML attribute to delete. + """ + + data_attrs = {} + attrs_map = { + 'body': 'data-comment-body', + 'title': 'data-comment-title', + 'problem': 'data-problem-id' + } + + for xml_key in attrs_map.keys(): + if xml_key in el.attrib: + value = el.get(xml_key, '') + html_key = attrs_map[xml_key] + data_attrs[html_key] = {'value': value, '_delete': xml_key} + + return data_attrs + + def _render_annotation(self, index, el): + """ Renders an annotation element for HTML output. """ + attr = {} + attr.update(self._get_annotation_class_attr(index, el)) + attr.update(self._get_annotation_data_attr(index, el)) + + el.tag = 'span' + + for key in attr.keys(): + el.set(key, attr[key]['value']) + if '_delete' in attr[key] and attr[key]['_delete'] is not None: + delete_key = attr[key]['_delete'] + del el.attrib[delete_key] + + def _render_content(self): + """ Renders annotatable content with annotation spans and returns HTML. """ + xmltree = etree.fromstring(self.content) + xmltree.tag = 'div' + if 'display_name' in xmltree.attrib: + del xmltree.attrib['display_name'] + + index = 0 + for el in xmltree.findall('.//annotation'): + self._render_annotation(index, el) + index += 1 + + return etree.tostring(xmltree, encoding='unicode') + + def _extract_instructions(self, xmltree): + """ Removes from the xmltree and returns them as a string, otherwise None. """ + instructions = xmltree.find('instructions') + if instructions is not None: + instructions.tag = 'div' + xmltree.remove(instructions) + return etree.tostring(instructions, encoding='unicode') + return None + + def get_html(self): + """ Renders parameters to template. """ + + extension = "" + if 'youtu' in self.sourceUrl: + extension = 'video/youtube' + else: + spliturl = self.sourceUrl.split(".") + extensionPlus1 = spliturl[len(spliturl)-1] + spliturl = extensionPlus1.split("?") + extensionPlus2 = spliturl[0] + spliturl = extensionPlus2.split("#") + extension = 'video/' + spliturl[0] + context = { + 'display_name': self.display_name_with_default, + 'element_id': self.element_id, + 'instructions_html': self.instructions, + 'sourceUrl': self.sourceUrl, + 'typeSource': extension, + 'poster': self.poster_url, + 'alert': self, + 'content_html': self._render_content(), + 'annotation_storage':self.annotation_storage_url + } + + return self.system.render_template('videoannotation.html', context) + + +class VideoAnnotationDescriptor(AnnotatableFields, RawDescriptor): + module_class = VideoAnnotationModule + mako_template = "widgets/raw-edit.html" diff --git a/common/static/css/vendor/f/1/vjs.eot b/common/static/css/vendor/f/1/vjs.eot new file mode 100644 index 0000000000000000000000000000000000000000..a075c19f0b5d7d01c0edf7741d1b733c8b123b72 GIT binary patch literal 3536 zcmds4O>7&-6@G7*4%9TWN`70-_Maz<`Mv22Hu8^ilEh&~IEBY~H z8MR%YQqbg(z$tUP(b^h&N&O#yL37;An9iw6L5VhQc9DVxPbT<9_-98L@4)WAX%QF}M_}X8#A%Bi~ zWq#(;#d;l{sO2vD8|Ig;o*(?N5hIe{A@bZ^n439Q`|L;mMBgrIaRCa~9|(P{LGE5y zUcci11(zZ3KptLNeQ8F0!)Idr66F5nnJX9REIot%LCDdSndP~YpTGNaqNYvgUcb0{ zX?-P>{Rif6LI19`HmvVX=PPfX^?v&cYPR$6(W^HwCy`C-yV4Gu5F4B{!4>|^`YxrU zn?yB|b}Ua~$X;o&Gyyt|QKAUPZ0X8EL}96g-y%0P@RNKV@+pUYL5Jwo{a6sjV!QWB z<^1S5Dw}jq#9&eiv2|}+F$oKM1z_G6k|mdg?m>-O{IrN1x-x}@6^cE@w8djXK}8Ka zD_etvRYP_GKG;xeH{ifj&B#4MR#8kcyY~3VzkT)yd;LTj`7zcFv?v(c2oKHF0%WP= zrFMi56p0B$;k{sO(QfxT_v`*&d6nYy7%k8T?BO84!SC>wk|qsGE7IR&pFA#4$?IaX z>ZSw?h%~lwOac(utXW$kA+J%c@;0)j5czX$2~o@2+vfH*Z`U??v$hFKdrwWSA{XQ@ z1_N!HC(VgM?!!h^ZM<5k@NXL3YHe0^H(ss6UgU+i0(&oY;y}jre5sgE>iJ?e6x0-X zp9c>6Ri&#-QT@um!1Io~Wv^d}OhpvGx1s+h{XDYYxj-B7uPxsZ!X0wZyZ)%z)-+Wy z3`NzHp`jPQX67<_jO&I1v+}L7{)jkSA`U6$#F3`Qzd4deM)oI6IWi(5o1A>%8=~~X zYNR?MqMW=tssGP0Gfme`-Ub%1i!66C(>4-q)~Rmg7;AEFF_|J%q^E$GSX+!!oYa$g zBCdE8m6a|I1@Tub6-&ptC&h`lC!hs$*+#Q1kl_~m9zlC);oKYX_E_|qp&p8ifDJyGch{Fh+CXCLm#j}?{$ z&;{Vd?H#Vy*~A_xKyL{9kfbz~Xo#p?3ucRXJsvzjJ&wFbbw`#C=&O2O*YmSI1zj)X z{D=Mi!xL6}V_%yH_lCp0wwGXbzdZ(ne_8(G|t}_{N;R|Fr_l?-U2sCkfU%G`) zoK2T#N+DaBECqQHes6Ep{=7Ibu{gocZQR-ziW{@nXN~v}n_|-2L3B(k{%m98Ryl55 zpPjvK#LIAuwfgE`;%@s4_uvQ-uqbdUFzQh}AseT_D1cflWdYDaUUVoPEJqkRU5=rm z0mUH?-1YW!r&3wt`FO0ojaiS!`})$UGm)sTNoH>K=h`FDqrH87r;i-*dYNNgNA#ZF z-to@Es>;4rx0!n(k!WvcP9_oq1DVWJEZPP)J+au)L!JIs=}d2=%j;u~MG`d29wMk7bPcrt!_e*F~(--^$Zmu2p%v zTD9`IhaC&MY-3lpu`7`U*NTN*Hf`|Mb}UgW1h0fGu^JS{+4VWR1ishdW$LDD4)22g zro+4OUHjPK#k=EQKry=-p;6(@<|XhQ4lmO<9>TWX1^v4Y@5ZC~R}Sxi{?5T?_SA)Q zbE{9_y?x-ZJvldjd1(f(?lJ4By>8JpJjdrKN?GgK9mSVEdcdEpGjLN6;BlTon?-9- z4vtn=*2h-Y=I5f>R3`dZ)R`HaQ5-Nb1KErLs{`-&2jM;B + + + +This is a custom SVG font generated by IcoMoon. + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/static/css/vendor/f/1/vjs.ttf b/common/static/css/vendor/f/1/vjs.ttf new file mode 100644 index 0000000000000000000000000000000000000000..eb2463791823ded2c3f9b1321e9fa3a331e8a5eb GIT binary patch literal 3372 zcmds4O>7&-6@G7*fn;iIyc-9T2d@aR`g@Y zGHSa(rJ~6pfm;+g2my>Dyd*%202X}dA5gI9p$G~jZDAlmqZWH~(ThDih#6;9iJ0w$ia`Noc7v6k#0SX_qq0{3NlQc#iqPBaGBhNgS z%A|g~KS0FKL!NzkZT`~lU;A?f@~3#NF3n%QRIkGmwcW*d)6(j-3&Y?td=}=fLLOY3zj}$z z(X$vIh8$U+Ut2u&>DxagYT1GA^-CLZG?v=< zC*-Ck{sv!weA=O((Ghx8OmHJl2Ti2=pp`F7oTrjS_XsgqltgU3J9bRM;vhu&xsYtR zByjniKNvi$`+wzCiqR9a zOz*LW1N;WR#h**MG%T%4f0cdmlsqeMiDcC+2^bJ%?BJ*bAhK1nQzD_R5w3CtRa1zx zY)4!?rAo!BRJc;x;howJEE_qsxQbekRtWezbWe)o`Rx16s@i<5T;^XjyVcr)>TbSP zg}tZ?aT)er>c)YL8M$I1moRdLOfaA;@*xi#(p06VM^QCpXy^sU-I`ZZ!n0vT^EM5B ze~`xyJGar!zqEaa33tfD-i^ntwyCR%X)3C&jE=ta1uK^@V%{(nn3ZmqjK{>`5_^=Q zP8=zE^2;N6Y-E4HlH=ndvYD9|za&ZxR^!!i5#`L?8RLJBnQ5+WaRpdF7Fq6QrV0ve z)v0dR7<+PVF`2?tpr?VDXh)QjoG=nbJf?UQm6aY22JkBs3&j!cOL9Es@#}$XrcjJ~ z;<0=#n+XJ?U#ymH-G5fv;1;js4Sn#JkXQCLGdFuB-_biCcKg`dQu~{0IFlL~DGUy~ zC)|<2;~l!hS=R|OH9A@tIN_djIXdh9eRiE5)1_9wzeUzhPJR8PCb#O6q_@i2*tz_Z z&zwAU=4<)Xbh*p_UxE$IL%1gmJ1hyH3&4xpJ5;Z;g&ZkBZxDG%P>PB)O4O+bGKHKG z3p_+Uj(k83N0uJaSB;!uXx}wB6r4)W<{pp-}&nzsK+I;a>}T<2(62 zO!dXXm)G~o;=SMi7OC-_l-r3z<(RJfnCqlhEnC0sA_pZxEx1_cY z9#NE@vuSbR3uHO>jmTdZnph(*y}~EXrb~3iU_+TG26zR2@9ft8xH3JxGR@C#-`*aL znF}`-%-ASfV$nMR3{0>5czgSHDQ4bSSh!)vN^p$5`s$zKZu=Pb;5ZSmC~zt;>QOww z22O!d0JTue0HFDt7*IUejxcnF979D1ih~}w>+kDLCNt&>v1n%pvk{9845X50!x3ML z%-pVJJHwIV{R0DMjve!QnWH_&jK2QGW(g(g8Pp z(dh9b-CDbJwm;nC^)bi7;e_#(vMPse80oX)JxYL-Ua_MyXz?~Z>0#q4T^MuoQqFM;oJc$uas z?eH$>-*$L61?U$J?}7dkd;?vi^R!4C^b|dZPu+{>7dM^)GXvccU7=N)r%i~9OIKFs z!A!z(owjVc35!LFP==CNErK_Fk%k4jpsoDTj_Xs5#-#Nk{L(9wlQ?3ht^9liK2XzX8D O(EG1%n1UYuukdfbdl*On literal 0 HcmV?d00001 diff --git a/common/static/css/vendor/f/1/vjs.woff b/common/static/css/vendor/f/1/vjs.woff new file mode 100644 index 0000000000000000000000000000000000000000..c3f0f1d80718ac2a16e2daeaf82ce59ed76a3f06 GIT binary patch literal 4228 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 + + + +This is a custom SVG font generated by IcoMoon. + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/static/css/vendor/ova/video-js.fw.png b/common/static/css/vendor/ova/video-js.fw.png new file mode 100644 index 0000000000000000000000000000000000000000..2c7f208c21813246bdd708fcd21db2863febe03b GIT binary patch literal 78899 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 literal 0 HcmV?d00001 diff --git a/common/static/css/vendor/ova/video-js.less b/common/static/css/vendor/ova/video-js.less new file mode 100644 index 000000000000..e5d1da112026 --- /dev/null +++ b/common/static/css/vendor/ova/video-js.less @@ -0,0 +1,949 @@ +/*! +Video.js Default Styles (http://videojs.com) +Version GENERATED_AT_BUILD +Create your own skin at http://designer.videojs.com +*/ + +// To customize the player skin, change the values of the variables or edit the +// CSS below. +// (This file uses LESS. Learn more at http://lesscss.org/) + +// The base font size controls the size of everything, not just text. All +// diminensions use em-based sizes so that the scale along with the font size. +// Try increasing it to 20px and see what happens. +@base-font-size: 10px; +@touch-device-font-size: 15px; + +// The main font color controls the color of the text and the icons (font icons) +@main-font-color: #CCCCCC; // e.g. rgb(255, 255, 255) or #ffffff + +// The default color of control backgrounds is mostly black but with a little +// bit of blue so it can still be seen on all black video frames, which are +// common. +@control-bg-color: #07141E; // e.g. rgb(255, 255, 255) or #ffffff +@control-bg-alpha: 0.7; // 1.0 = 100% opacity, 0.0 = 0% opacity + +// The slider bar color is used for the progress bar and the volume bar +@slider-bar-color: #66A8CC; // e.g. rgb(255, 255, 255) or #ffffff +// The background of the progress bar and volume bar have a lined pattern that +// is created from a base64 encoded image. You can generate your own pattern at +// http://www.patternify.com/ then replace the value in the quotes with your own +@slider-bar-pattern: ~'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAP0lEQVQIHWWMAQoAIAgDR/QJ/Ub//04+w7ZICBwcOg5FZi5iBB82AGzixEglJrd4TVK5XUJpskSTEvpdFzX9AB2pGziSQcvAAAAAAElFTkSuQmCC'; +// The color of the slider background +@slider-background-color: #333333; +@slider-background-alpha: 0.9; // 1.0 = 100% opacity, 0.0 = 0% opacity + +// The "Big Play Button" is the play button that shows before the video plays. +// To center it set the align values to center and middle. The typical location +// of the button is the center, but there is trend towards moving it to a corner +// where it gets out of the way of valuable content in the poster image. +@big-play-align: left; // left, center, or right +@big-play-vertical-align: top; // top, middle, or bottom +// The button colors match the control colors by default but you can customize +// them by replace the variables (@control-bg-color) with your own color values. +@big-play-bg-color: @control-bg-color; +@big-play-bg-alpha: @control-bg-alpha; +// The font size is what makes the big play button, big. All width/height values +// use ems, which are a multiple of the font size. +// If the @base-font-size is 10px, then 3em equals 30px. +@big-play-font-size: 3em; +// Now that font size is set, the following em values will be a multiple of the +// new font size. If @big-play-font-size is 3em (30px), then setting the any of +// the following values to 2em would equal 60px. 2 * font-size +@big-play-margin: 0.5em; +@big-play-width: 4em; +@big-play-height: 2.6em; +@big-play-border-radius: 0.8em; +@big-play-border-width: 0.1em; +@big-play-border-color: #3b4249; + +/* SKIN +================================================================================ +The main class name for all skin-specific styles. To make your own skin, +replace all occurances of 'vjs-default-skin' with a new name. Then add your new +skin name to your video tag instead of the default skin. +e.g.