Merge pull request #18560 from edx/lduarte1991-annotations_deprecation

Lduarte1991 annotations deprecation
This commit is contained in:
Feanil Patel
2018-07-17 10:20:49 -04:00
committed by GitHub
114 changed files with 4 additions and 40841 deletions

View File

@@ -695,8 +695,7 @@ class MiscCourseTests(ContentStoreTestCase):
# page response HTML
self.check_components_on_page(
ADVANCED_COMPONENT_TYPES,
['Word cloud', 'Annotation', 'Text Annotation', 'Video Annotation', 'Image Annotation',
'split_test'],
['Word cloud', 'Annotation', 'split_test'],
)
@ddt.data('/Fake/asset/displayname', '\\Fake\\asset\\displayname')

View File

@@ -128,28 +128,7 @@
'tooltip_manager': 'js/src/tooltip_manager',
'draggabilly': 'js/vendor/draggabilly',
'hls': 'common/js/vendor/hls',
// Files needed for Annotations feature
'annotator': 'js/vendor/ova/annotator-full',
'annotator-harvardx': 'js/vendor/ova/annotator-full-firebase-auth',
'video.dev': 'js/vendor/ova/video.dev',
'vjs.youtube': 'js/vendor/ova/vjs.youtube',
'rangeslider': 'js/vendor/ova/rangeslider',
'share-annotator': 'js/vendor/ova/share-annotator',
'richText-annotator': 'js/vendor/ova/richText-annotator',
'reply-annotator': 'js/vendor/ova/reply-annotator',
'grouping-annotator': 'js/vendor/ova/grouping-annotator',
'tags-annotator': 'js/vendor/ova/tags-annotator',
'diacritic-annotator': 'js/vendor/ova/diacritic-annotator',
'flagging-annotator': 'js/vendor/ova/flagging-annotator',
'jquery-Watch': 'js/vendor/ova/jquery-Watch',
'openseadragon': 'js/vendor/ova/openseadragon',
'osda': 'js/vendor/ova/OpenSeaDragonAnnotation',
'ova': 'js/vendor/ova/ova',
'catch': 'js/vendor/ova/catch/js/catch',
'handlebars': 'js/vendor/ova/catch/js/handlebars-1.1.2',
'lang_edx': 'js/src/lang_edx',
// end of Annotation tool files
// externally hosted files
mathjax: '//cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_SVG&delayStartupUntil=configured', // eslint-disable-line max-len

View File

@@ -28,9 +28,6 @@ XMODULES = [
"custom_tag_template = xmodule.raw_module:RawDescriptor",
"about = xmodule.html_module:AboutDescriptor",
"annotatable = xmodule.annotatable_module:AnnotatableDescriptor",
"textannotation = xmodule.textannotation_module:TextAnnotationDescriptor",
"videoannotation = xmodule.videoannotation_module:VideoAnnotationDescriptor",
"imageannotation = xmodule.imageannotation_module:ImageAnnotationDescriptor",
"word_cloud = xmodule.word_cloud_module:WordCloudDescriptor",
"hidden = xmodule.hidden_module:HiddenDescriptor",
"raw = xmodule.raw_module:RawDescriptor",

View File

@@ -1,162 +0,0 @@
"""
Module for Image annotations using annotator.
"""
import textwrap
from lxml import etree
from pkg_resources import resource_string
from web_fragments.fragment import Fragment
from xblock.core import Scope, String
from xmodule.annotator_mixin import get_instructions, html_to_text
from xmodule.annotator_token import retrieve_token
from xmodule.raw_module import RawDescriptor
from xmodule.x_module import XModule
# Make '_' a no-op so we can scrape strings. Using lambda instead of
# `django.utils.translation.ugettext_noop` because Django cannot be imported in this file
_ = lambda text: text
class AnnotatableFields(object):
""" Fields for `ImageModule` and `ImageDescriptor`. """
data = String(
help=_("XML data for the annotation"),
scope=Scope.content,
default=textwrap.dedent("""\
<annotatable>
<instructions>
<p>
Add the instructions to the assignment here.
</p>
</instructions>
<p>
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.
</p>
<json>
navigatorSizeRatio: 0.25,
wrapHorizontal: false,
showNavigator: true,
navigatorPosition: "BOTTOM_LEFT",
showNavigationControl: true,
tileSources: [{"profile": "http://library.stanford.edu/iiif/image-api/1.1/compliance.html#level2", "scale_factors": [1, 2, 4, 8, 16, 32, 64], "tile_height": 1024, "height": 3466, "width": 113793, "tile_width": 1024, "qualities": ["native", "bitonal", "grey", "color"], "formats": ["jpg", "png", "gif"], "@context": "http://library.stanford.edu/iiif/image-api/1.1/context.json", "@id": "http://54.187.32.48/loris/suzhou_orig.jp2"}],
</json>
</annotatable>
"""))
display_name = String(
display_name=_("Display Name"),
help=_("The display name for this component."),
scope=Scope.settings,
default=_('Image Annotation'),
)
instructor_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='professor:green,teachingAssistant:blue',
)
annotation_storage_url = String(
help=_("Location of Annotation backend"),
scope=Scope.settings,
default="http://your_annotation_storage.com",
display_name=_("Url for Annotation Storage")
)
annotation_token_secret = String(
help=_("Secret string for annotation storage"),
scope=Scope.settings,
default="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
display_name=_("Secret Token String for Annotation")
)
default_tab = String(
display_name=_("Default Annotations Tab"),
help=_("Select which tab will be the default in the annotations table: myNotes, Instructor, or Public."),
scope=Scope.settings,
default="myNotes",
)
# currently only supports one instructor, will build functionality for multiple later
instructor_email = String(
display_name=_("Email for 'Instructor' Annotations"),
help=_("Email of the user that will be attached to all annotations that will be found in 'Instructor' tab."),
scope=Scope.settings,
default="",
)
annotation_mode = String(
display_name=_("Mode for Annotation Tool"),
help=_("Type in number corresponding to following modes: 'instructor' or 'everyone'"),
scope=Scope.settings,
default="everyone",
)
class ImageAnnotationModule(AnnotatableFields, XModule):
'''Image Annotation Module'''
js = {
'js': [
resource_string(__name__, 'js/src/html/display.js'),
resource_string(__name__, 'js/src/annotatable/display.js'),
resource_string(__name__, 'js/src/javascript_loader.js'),
resource_string(__name__, 'js/src/collapsible.js'),
]
}
css = {'scss': [resource_string(__name__, 'css/annotatable/display.scss')]}
icon_class = 'imageannotation'
def __init__(self, *args, **kwargs):
super(ImageAnnotationModule, self).__init__(*args, **kwargs)
xmltree = etree.fromstring(self.data)
self.instructions = self._extract_instructions(xmltree)
self.openseadragonjson = html_to_text(etree.tostring(xmltree.find('json'), encoding='unicode'))
self.user_email = ""
self.is_course_staff = False
if self.runtime.get_user_role() in ['instructor', 'staff']:
self.is_course_staff = True
if self.runtime.get_real_user is not None:
try:
self.user_email = self.runtime.get_real_user(self.runtime.anonymous_student_id).email
except Exception: # pylint: disable=broad-except
self.user_email = _("No email address found.")
def _extract_instructions(self, xmltree):
""" Removes <instructions> from the xmltree and returns them as a string, otherwise None. """
return get_instructions(xmltree)
def student_view(self, context):
""" Renders parameters to template. """
context = {
'display_name': self.display_name_with_default_escaped,
'instructions_html': self.instructions,
'token': retrieve_token(self.user_email, self.annotation_token_secret),
'tag': self.instructor_tags,
'openseadragonjson': self.openseadragonjson,
'annotation_storage': self.annotation_storage_url,
'default_tab': self.default_tab,
'instructor_email': self.instructor_email,
'annotation_mode': self.annotation_mode,
'is_course_staff': self.is_course_staff,
}
fragment = Fragment(self.system.render_template('imageannotation.html', context))
# TinyMCE already exists in Studio so we should not load the files again
# get_real_user always returns "None" in Studio since its runtimes contains no anonymous ids
if self.runtime.get_real_user is not None:
fragment.add_javascript_url(self.runtime.STATIC_URL + "js/vendor/tinymce/js/tinymce/tinymce.full.min.js")
fragment.add_javascript_url(self.runtime.STATIC_URL + "js/vendor/tinymce/js/tinymce/jquery.tinymce.min.js")
return fragment
class ImageAnnotationDescriptor(AnnotatableFields, RawDescriptor):
''' Image annotation descriptor '''
module_class = ImageAnnotationModule
resources_dir = None
mako_template = "widgets/raw-edit.html"
@property
def non_editable_metadata_fields(self):
non_editable_fields = super(ImageAnnotationDescriptor, self).non_editable_metadata_fields
non_editable_fields.extend([
ImageAnnotationDescriptor.annotation_storage_url,
ImageAnnotationDescriptor.annotation_token_secret,
])
return non_editable_fields

View File

@@ -68,18 +68,6 @@ class InheritanceMixin(XBlockMixin):
help=_("This setting is not currently supported."), scope=Scope.settings,
deprecated=True
)
annotation_storage_url = String(
help=_("Enter the location of the annotation storage server. The textannotation, videoannotation, and imageannotation advanced modules require this setting."),
scope=Scope.settings,
default="http://your_annotation_storage.com",
display_name=_("URL for Annotation Storage")
)
annotation_token_secret = String(
help=_("Enter the secret string for annotation storage. The textannotation, videoannotation, and imageannotation advanced modules require this string."),
scope=Scope.settings,
default="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
display_name=_("Secret Token String for Annotation")
)
graceperiod = Timedelta(
help="Amount of time after the due date that submissions will be accepted",
scope=Scope.settings,

View File

@@ -1,106 +0,0 @@
# -*- coding: utf-8 -*-
"""Test for Image 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.imageannotation_module import ImageAnnotationModule
from . import get_test_system
class ImageAnnotationModuleTestCase(unittest.TestCase):
''' Image Annotation Module Test Case '''
sample_xml = '''
<annotatable>
<instructions><p>Image Test Instructions.</p></instructions>
<json>
navigatorSizeRatio: 0.25,
wrapHorizontal: false,
showNavigator: true,
navigatorPosition: "BOTTOM_LEFT",
showNavigationControl: true,
tileSources: [{
Image: {
xmlns: "http://schemas.microsoft.com/deepzoom/2009",
Url: "http://static.seadragon.com/content/misc/milwaukee_files/",
TileSize: "254",
Overlap: "1",
Format: "jpg",
ServerFormat: "Default",
Size: {
Width: "15497",
Height: "5378"
}
}
},],
</json>
</annotatable>
'''
shard = 1
def setUp(self):
"""
Makes sure that the Module is declared and mocked with the sample xml above.
"""
super(ImageAnnotationModuleTestCase, self).setUp()
# return anything except None to test LMS
def test_real_user(useless):
useless_user = Mock(email='fake@fake.com', id=useless)
return useless_user
# test to make sure that role is checked in LMS
def test_user_role():
return 'staff'
self.system = get_test_system()
self.system.get_real_user = test_real_user
self.system.get_user_role = test_user_role
self.system.anonymous_student_id = None
self.mod = ImageAnnotationModule(
Mock(),
self.system,
DictFieldData({'data': self.sample_xml}),
ScopeIds(None, None, None, None)
)
def test_extract_instructions(self):
"""
Tests to make sure that the instructions are correctly pulled from the sample xml above.
It also makes sure that if no instructions exist, that it does in fact return nothing.
"""
xmltree = etree.fromstring(self.sample_xml)
expected_xml = u"<div><p>Image Test Instructions.</p></div>"
actual_xml = self.mod._extract_instructions(xmltree) # pylint: disable=protected-access
self.assertIsNotNone(actual_xml)
self.assertEqual(expected_xml.strip(), actual_xml.strip())
xmltree = etree.fromstring('<annotatable>foo</annotatable>')
actual = self.mod._extract_instructions(xmltree) # pylint: disable=protected-access
self.assertIsNone(actual)
def test_student_view(self):
"""
Tests the function that passes in all the information in the context
that will be used in templates/imageannotation.html
"""
context = self.mod.student_view({}).content
for key in ['display_name',
'instructions_html',
'annotation_storage',
'token',
'tag',
'openseadragonjson',
'default_tab',
'instructor_email',
'annotation_mode',
'is_course_staff']:
self.assertIn(key, context)

View File

@@ -1,91 +0,0 @@
# -*- 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 . import get_test_system
class TextAnnotationModuleTestCase(unittest.TestCase):
''' text Annotation Module Test Case '''
sample_xml = '''
<annotatable>
<instructions><p>Test Instructions.</p></instructions>
<p>
One Fish. Two Fish.
Red Fish. Blue Fish.
Oh the places you'll go!
</p>
</annotatable>
'''
shard = 1
def setUp(self):
"""
Makes sure that the Module is declared and mocked with the sample xml above.
"""
super(TextAnnotationModuleTestCase, self).setUp()
# return anything except None to test LMS
def test_real_user(useless):
useless_user = Mock(email='fake@fake.com', id=useless)
return useless_user
# test to make sure that role is checked in LMS
def test_user_role():
return 'staff'
self.system = get_test_system()
self.system.get_real_user = test_real_user
self.system.get_user_role = test_user_role
self.system.anonymous_student_id = None
self.mod = TextAnnotationModule(
Mock(),
self.system,
DictFieldData({'data': self.sample_xml}),
ScopeIds(None, None, None, None)
)
def test_extract_instructions(self):
"""
Tests to make sure that the instructions are correctly pulled from the sample xml above.
It also makes sure that if no instructions exist, that it does in fact return nothing.
"""
xmltree = etree.fromstring(self.sample_xml)
expected_xml = u"<div><p>Test Instructions.</p></div>"
actual_xml = self.mod._extract_instructions(xmltree) # pylint: disable=protected-access
self.assertIsNotNone(actual_xml)
self.assertEqual(expected_xml.strip(), actual_xml.strip())
xmltree = etree.fromstring('<annotatable>foo</annotatable>')
actual = self.mod._extract_instructions(xmltree) # pylint: disable=protected-access
self.assertIsNone(actual)
def test_student_view(self):
"""
Tests the function that passes in all the information in the context
that will be used in templates/textannotation.html
"""
context = self.mod.student_view({}).content
for key in ['display_name',
'tag',
'source',
'instructions_html',
'content_html',
'annotation_storage',
'token',
'diacritic_marks',
'default_tab',
'annotation_mode',
'is_course_staff']:
self.assertIn(key, context)

View File

@@ -1,97 +0,0 @@
# -*- 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.videoannotation_module import VideoAnnotationModule
from . import get_test_system
class VideoAnnotationModuleTestCase(unittest.TestCase):
''' Video Annotation Module Test Case '''
sample_xml = '''
<annotatable>
<instructions><p>Video Test Instructions.</p></instructions>
</annotatable>
'''
shard = 1
sample_sourceurl = "http://video-js.zencoder.com/oceans-clip.mp4"
sample_youtubeurl = "http://www.youtube.com/watch?v=yxLIu-scR9Y"
def setUp(self):
"""
Makes sure that the Video Annotation Module is created.
"""
super(VideoAnnotationModuleTestCase, self).setUp()
# return anything except None to test LMS
def test_real_user(useless):
useless_user = Mock(email='fake@fake.com', id=useless)
return useless_user
# test to make sure that role is checked in LMS
def test_user_role():
return 'staff'
self.system = get_test_system()
self.system.get_real_user = test_real_user
self.system.get_user_role = test_user_role
self.system.anonymous_student_id = None
self.mod = VideoAnnotationModule(
Mock(),
self.system,
DictFieldData({'data': self.sample_xml, 'sourceUrl': self.sample_sourceurl}),
ScopeIds(None, None, None, None)
)
def test_extract_instructions(self):
"""
This test ensures that if an instruction exists it is pulled and
formatted from the <instructions> tags. Otherwise, it should return nothing.
"""
xmltree = etree.fromstring(self.sample_xml)
expected_xml = u"<div><p>Video Test Instructions.</p></div>"
actual_xml = self.mod._extract_instructions(xmltree) # pylint: disable=protected-access
self.assertIsNotNone(actual_xml)
self.assertEqual(expected_xml.strip(), actual_xml.strip())
xmltree = etree.fromstring('<annotatable>foo</annotatable>')
actual = self.mod._extract_instructions(xmltree) # pylint: disable=protected-access
self.assertIsNone(actual)
def test_get_extension(self):
"""
Tests the function that returns the appropriate extension depending on whether it is
a video from youtube, or one uploaded to the EdX server.
"""
expectedyoutube = 'video/youtube'
expectednotyoutube = 'video/mp4'
result1 = self.mod._get_extension(self.sample_sourceurl) # pylint: disable=protected-access
result2 = self.mod._get_extension(self.sample_youtubeurl) # pylint: disable=protected-access
self.assertEqual(expectedyoutube, result2)
self.assertEqual(expectednotyoutube, result1)
def test_student_view(self):
"""
Tests to make sure variables passed in truly exist within the html once it is all rendered.
"""
context = self.mod.student_view({}).content
for key in ['display_name',
'instructions_html',
'sourceUrl',
'typeSource',
'poster',
'annotation_storage',
'default_tab',
'instructor_email',
'annotation_mode',
'is_course_staff']:
self.assertIn(key, context)

View File

@@ -1,160 +0,0 @@
"""Text annotation module"""
import textwrap
from lxml import etree
from pkg_resources import resource_string
from web_fragments.fragment import Fragment
from xblock.core import Scope, String
from xmodule.annotator_mixin import get_instructions
from xmodule.annotator_token import retrieve_token
from xmodule.raw_module import RawDescriptor
from xmodule.x_module import XModule
# Make '_' a no-op so we can scrape strings. Using lambda instead of
# `django.utils.translation.ugettext_noop` because Django cannot be imported in this file
_ = lambda text: text
class AnnotatableFields(object):
"""Fields for `TextModule` and `TextDescriptor`."""
data = String(
help=_("XML data for the annotation"),
scope=Scope.content,
default=textwrap.dedent("""\
<annotatable>
<instructions>
<p>
Add the instructions to the assignment here.
</p>
</instructions>
<p>
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.
</p>
</annotatable>
"""))
display_name = String(
display_name=_("Display Name"),
help=_("The display name for this component."),
scope=Scope.settings,
default=_('Text Annotation'),
)
instructor_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 <a href=\"http://easybib.com\">EasyBib</a>"),
scope=Scope.settings,
default='None',
)
diacritics = String(
display_name=_("Diacritic Marks"),
help=_("Add diacritic marks to be added to a text using the comma-separated form, i.e. markname;urltomark;baseline,markname2;urltomark2;baseline2"),
scope=Scope.settings,
default='',
)
annotation_storage_url = String(
help=_("Location of Annotation backend"),
scope=Scope.settings,
default="http://your_annotation_storage.com",
display_name=_("Url for Annotation Storage")
)
annotation_token_secret = String(
help=_("Secret string for annotation storage"),
scope=Scope.settings,
default="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
display_name=_("Secret Token String for Annotation")
)
default_tab = String(
display_name=_("Default Annotations Tab"),
help=_("Select which tab will be the default in the annotations table: myNotes, Instructor, or Public."),
scope=Scope.settings,
default="myNotes",
)
# currently only supports one instructor, will build functionality for multiple later
instructor_email = String(
display_name=_("Email for 'Instructor' Annotations"),
help=_("Email of the user that will be attached to all annotations that will be found in 'Instructor' tab."),
scope=Scope.settings,
default="",
)
annotation_mode = String(
display_name=_("Mode for Annotation Tool"),
help=_("Type in number corresponding to following modes: 'instructor' or 'everyone'"),
scope=Scope.settings,
default="everyone",
)
class TextAnnotationModule(AnnotatableFields, XModule):
''' Text Annotation Module '''
js = {'js': []}
css = {'scss': [resource_string(__name__, 'css/annotatable/display.scss')]}
icon_class = 'textannotation'
def __init__(self, *args, **kwargs):
super(TextAnnotationModule, self).__init__(*args, **kwargs)
xmltree = etree.fromstring(self.data)
self.instructions = self._extract_instructions(xmltree)
self.content = etree.tostring(xmltree, encoding='unicode')
self.user_email = ""
self.is_course_staff = False
if self.runtime.get_user_role() in ['instructor', 'staff']:
self.is_course_staff = True
if self.runtime.get_real_user is not None:
try:
self.user_email = self.runtime.get_real_user(self.runtime.anonymous_student_id).email
except Exception: # pylint: disable=broad-except
self.user_email = _("No email address found.")
def _extract_instructions(self, xmltree):
""" Removes <instructions> from the xmltree and returns them as a string, otherwise None. """
return get_instructions(xmltree)
def student_view(self, context):
""" Renders parameters to template. """
context = {
'course_key': self.runtime.course_id,
'display_name': self.display_name_with_default_escaped,
'tag': self.instructor_tags,
'source': self.source,
'instructions_html': self.instructions,
'content_html': self.content,
'token': retrieve_token(self.user_email, self.annotation_token_secret),
'diacritic_marks': self.diacritics,
'annotation_storage': self.annotation_storage_url,
'default_tab': self.default_tab,
'instructor_email': self.instructor_email,
'annotation_mode': self.annotation_mode,
'is_course_staff': self.is_course_staff,
}
fragment = Fragment(self.system.render_template('textannotation.html', context))
# TinyMCE already exists in Studio so we should not load the files again
# get_real_user always returns "None" in Studio since its runtimes contains no anonymous ids
if self.runtime.get_real_user is not None:
fragment.add_javascript_url(self.runtime.STATIC_URL + "js/vendor/tinymce/js/tinymce/tinymce.full.min.js")
fragment.add_javascript_url(self.runtime.STATIC_URL + "js/vendor/tinymce/js/tinymce/jquery.tinymce.min.js")
return fragment
class TextAnnotationDescriptor(AnnotatableFields, RawDescriptor):
''' Text Annotation Descriptor '''
module_class = TextAnnotationModule
resources_dir = None
mako_template = "widgets/raw-edit.html"
@property
def non_editable_metadata_fields(self):
non_editable_fields = super(TextAnnotationDescriptor, self).non_editable_metadata_fields
non_editable_fields.extend([
TextAnnotationDescriptor.annotation_storage_url,
TextAnnotationDescriptor.annotation_token_secret,
])
return non_editable_fields

View File

@@ -1,165 +0,0 @@
"""
Module for Video annotations using annotator.
"""
import textwrap
from lxml import etree
from pkg_resources import resource_string
from web_fragments.fragment import Fragment
from xblock.core import Scope, String
from xmodule.annotator_mixin import get_extension, get_instructions
from xmodule.annotator_token import retrieve_token
from xmodule.raw_module import RawDescriptor
from xmodule.x_module import XModule
# Make '_' a no-op so we can scrape strings. Using lambda instead of
# `django.utils.translation.ugettext_noop` because Django cannot be imported in this file
_ = lambda text: text
class AnnotatableFields(object):
""" Fields for `VideoModule` and `VideoDescriptor`. """
data = String(
help=_("XML data for the annotation"),
scope=Scope.content,
default=textwrap.dedent("""\
<annotatable>
<instructions>
<p>
Add the instructions to the assignment here.
</p>
</instructions>
</annotatable>
"""))
display_name = String(
display_name=_("Display Name"),
help=_("The display name for this component."),
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=""
)
annotation_storage_url = String(
help=_("Location of Annotation backend"),
scope=Scope.settings,
default="http://your_annotation_storage.com",
display_name=_("Url for Annotation Storage")
)
annotation_token_secret = String(
help=_("Secret string for annotation storage"),
scope=Scope.settings,
default="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
display_name=_("Secret Token String for Annotation")
)
default_tab = String(
display_name=_("Default Annotations Tab"),
help=_("Select which tab will be the default in the annotations table: myNotes, Instructor, or Public."),
scope=Scope.settings,
default="myNotes",
)
# currently only supports one instructor, will build functionality for multiple later
instructor_email = String(
display_name=_("Email for 'Instructor' Annotations"),
help=_("Email of the user that will be attached to all annotations that will be found in 'Instructor' tab."),
scope=Scope.settings,
default="",
)
annotation_mode = String(
display_name=_("Mode for Annotation Tool"),
help=_("Type in number corresponding to following modes: 'instructor' or 'everyone'"),
scope=Scope.settings,
default="everyone",
)
class VideoAnnotationModule(AnnotatableFields, XModule):
'''Video Annotation Module'''
js = {
'js': [
resource_string(__name__, 'js/src/html/display.js'),
resource_string(__name__, 'js/src/annotatable/display.js'),
resource_string(__name__, 'js/src/javascript_loader.js'),
resource_string(__name__, 'js/src/collapsible.js'),
]
}
css = {'scss': [resource_string(__name__, 'css/annotatable/display.scss')]}
icon_class = 'videoannotation'
def __init__(self, *args, **kwargs):
super(VideoAnnotationModule, self).__init__(*args, **kwargs)
xmltree = etree.fromstring(self.data)
self.instructions = self._extract_instructions(xmltree)
self.content = etree.tostring(xmltree, encoding='unicode')
self.user_email = ""
self.is_course_staff = False
if self.runtime.get_user_role() in ['instructor', 'staff']:
self.is_course_staff = True
if self.runtime.get_real_user is not None:
try:
self.user_email = self.runtime.get_real_user(self.runtime.anonymous_student_id).email
except Exception: # pylint: disable=broad-except
self.user_email = _("No email address found.")
def _extract_instructions(self, xmltree):
""" Removes <instructions> from the xmltree and returns them as a string, otherwise None. """
return get_instructions(xmltree)
def _get_extension(self, src_url):
''' get the extension of a given url '''
return get_extension(src_url)
def student_view(self, context):
""" Renders parameters to template. """
extension = self._get_extension(self.sourceurl)
context = {
'course_key': self.runtime.course_id,
'display_name': self.display_name_with_default_escaped,
'instructions_html': self.instructions,
'sourceUrl': self.sourceurl,
'typeSource': extension,
'poster': self.poster_url,
'content_html': self.content,
'token': retrieve_token(self.user_email, self.annotation_token_secret),
'annotation_storage': self.annotation_storage_url,
'default_tab': self.default_tab,
'instructor_email': self.instructor_email,
'annotation_mode': self.annotation_mode,
'is_course_staff': self.is_course_staff,
}
fragment = Fragment(self.system.render_template('videoannotation.html', context))
# TinyMCE already exists in Studio so we should not load the files again
# get_real_user always returns "None" in Studio since its runtimes contains no anonymous ids
if self.runtime.get_real_user is not None:
fragment.add_javascript_url(self.runtime.STATIC_URL + "js/vendor/tinymce/js/tinymce/tinymce.full.min.js")
fragment.add_javascript_url(self.runtime.STATIC_URL + "js/vendor/tinymce/js/tinymce/jquery.tinymce.min.js")
return fragment
class VideoAnnotationDescriptor(AnnotatableFields, RawDescriptor):
''' Video annotation descriptor '''
module_class = VideoAnnotationModule
resources_dir = None
mako_template = "widgets/raw-edit.html"
@property
def non_editable_metadata_fields(self):
non_editable_fields = super(VideoAnnotationDescriptor, self).non_editable_metadata_fields
non_editable_fields.extend([
VideoAnnotationDescriptor.annotation_storage_url,
VideoAnnotationDescriptor.annotation_token_secret,
])
return non_editable_fields

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
.mark{
width: 10px;
height: 10px;
position: absolute;
background-size: contain;
background-repeat: no-repeat;
background-position: 50% 0%;
}

View File

@@ -1,108 +0,0 @@
/*This is written to fix some design problems with edX*/
.annotatable-wrapper .annotatable-header .annotatable-title{
padding-top: 20px !important;
}
.annotator-wrapper .annotator-adder button {
opacity:0;
}
.annotator-editor a, .annotator-filter .annotator-filter-property label{
line-height: 24px !important;
color: #363636 !important;
font-size: 12px!important;
font-weight: bold !important;
text-shadow: none !important;
}
.annotator-outer ul {
list-style: none !important;
padding-left: 0em !important;
}
.annotator-outer li {
margin-bottom: 0em!important;
}
.vjs-rangeslider-holder span.vjs-time-text{
line-height: 1!important;
float: left;
}
span.annotator-hl{
font:inherit;
}
.vjs-has-started .vjs-loading-spinner {
display: none!important;
}
/*Catch*/
#mainCatch *{
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
/*PublicPrivate Notes in My notes */
.notes-wrapper .PublicPrivate.separator,
.notes-wrapper .PublicPrivate.myNotes{
position:relative;
float:left;
}
.notes-wrapper .PublicPrivate.active *{
color:black;
}
/* My notes buttons */
.notes-wrapper .buttonCatch{
-moz-box-shadow:inset 0px 1px 0px 0px #ffffff;
-webkit-box-shadow:inset 0px 1px 0px 0px #ffffff;
box-shadow:inset 0px 1px 0px 0px #ffffff;
background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #ffffff), color-stop(1, #a6a3a3));
background:-moz-linear-gradient(top, #ffffff 5%, #a6a3a3 100%);
background:-webkit-linear-gradient(top, #ffffff 5%, #a6a3a3 100%);
background:-o-linear-gradient(top, #ffffff 5%, #a6a3a3 100%);
background:-ms-linear-gradient(top, #ffffff 5%, #a6a3a3 100%);
background:linear-gradient(to bottom, #ffffff 5%, #a6a3a3 100%);
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#a6a3a3',GradientType=0);
background-color:#ffffff;
-moz-border-radius:6px;
-webkit-border-radius:6px;
border-radius:6px;
border:1px solid #c2c2c2;
display:inline-block;
color:#302f2f;
font-family:arial;
font-size:15px;
font-weight:bold;
padding:6px 24px;
text-decoration:none;
text-shadow:0px 1px 0px #ffffff;
margin: 0px 5px 10px 5px;
cursor:pointer;
}
.notes-wrapper .buttonCatch.active{
color:red;
}
.notes-wrapper .buttonCatch:hover {
background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #a6a3a3), color-stop(1, #ffffff));
background:-moz-linear-gradient(top, #a6a3a3 5%, #ffffff 100%);
background:-webkit-linear-gradient(top, #a6a3a3 5%, #ffffff 100%);
background:-o-linear-gradient(top, #a6a3a3 5%, #ffffff 100%);
background:-ms-linear-gradient(top, #a6a3a3 5%, #ffffff 100%);
background:linear-gradient(to bottom, #a6a3a3 5%, #ffffff 100%);
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#a6a3a3', endColorstr='#ffffff',GradientType=0);
background-color:#a6a3a3;
}
.notes-wrapper .buttonCatch:active {
position:relative;
top:1px;
}
.annotatable-content #sourceCitation {
color:#CCC;
font-style:italic;
font-size:12px;
}

View File

@@ -1,27 +0,0 @@
.flag-icon{
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAsCAMAAAAgsQpJAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAytpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDQ1NzExMTM2MEUwMTFFM0I2RjhDOENEOEZGRUY1MzQiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDQ1NzExMTI2MEUwMTFFM0I2RjhDOENEOEZGRUY1MzQiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5kaWQ6YWNmNmE5ZGQtZDlkOC00YTlhLThmMjAtY2EzNGM5ODcxZDJhIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmFjZjZhOWRkLWQ5ZDgtNGE5YS04ZjIwLWNhMzRjOTg3MWQyYSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pnen528AAAAJUExURc3Nzf///////3aZ7dEAAAADdFJOU///ANfKDUEAAACzSURBVHjarNRLFoJADETRZ+1/0cpAYuevx8w4XOjQdApZ8SpVxQ+QJYRW4hzV+3GO4rk3hFNCWMG765a7NEhbBtlBxtK86peQNbws/y+teoz/ofiWFbSTtHLTHt0TErddqfMHNxxGWzUbj8SlUIdL5trBc9Br6AKh7PHh5pXc1XM9uQiT9lJYOQc//mGXj51LgrTIPpbOBWmTuizaC/moOZr79k44uDtIJ3cmriao2ekpwADT/geMPTQb1AAAAABJRU5ErkJggg==");
background-repeat: no-repeat;
background-size:13px 13px;
top: 2px;
left: 5px;
float: left;
border: none;
width: 13px;
height: 13px;
cursor: pointer;
position: absolute;
}
.flag-icon-used, .flag-icon:hover{
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAsCAMAAAAgsQpJAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAytpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDQ1NzExMEY2MEUwMTFFM0I2RjhDOENEOEZGRUY1MzQiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDQ1NzExMEU2MEUwMTFFM0I2RjhDOENEOEZGRUY1MzQiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5kaWQ6YWNmNmE5ZGQtZDlkOC00YTlhLThmMjAtY2EzNGM5ODcxZDJhIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmFjZjZhOWRkLWQ5ZDgtNGE5YS04ZjIwLWNhMzRjOTg3MWQyYSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PpBey0IAAAAVUExURQAAAAEBAQ4ODrGxscHBwfj4+P///6napTIAAAAHdFJOU////////wAaSwNGAAABW0lEQVR42oyVWQLDIAhEBwZy/yNX3EpSo+WrSV+GVcT1NVf1682Qfquq/QNSAP4BEhC8+56gAUFOSVKVC9BUg4Sm7zQnh5GwVMWhwngQTR4w9KSRUkWIZuWlZZBNr5NKxbTpHcPP/Cscfp8gHKAT2URE8iO6c7jiYK0QUNlj0vuKu6c1auZFEUdOQ/UcY3FZuqm4eOKiO0Xtug4x1qaG4l6ydsZYwS1ZueLde6+TguXs2CafY3p8TI/SyyjN0rL5szy4LEPD1lZNaRjRO7M4HtbaGkCpcp+zFRiSZS4tPpkjvgTjYATHOY2vIOTBLcFyMki32yFcgZQQ8ju3AFnLZxIl3YFtU9nPGsIv56H6s9fwKHVwkbTv9mMPrNC07SJtgcXcHxZp4wDbL1KNBOKo2XaRek/jdd8jcy/h3fcjH0OwBqsSd5dCAy247S3TwYhQd9dWjnHVjWwfAQYAR+4aJLhjvXgAAAAASUVORK5CYII=");
background-repeat: no-repeat;
background-size:13px 13px;
top: 2px;
left: 5px;
float: left;
border: none;
width: 13px;
height: 13px;
cursor: pointer;
position: absolute;
}

View File

@@ -1,49 +0,0 @@
.groupButton {
background-color: rgba(255, 255, 10, 0.3);
position: absolute;
width: 30px;
text-align: center;
right: -17px;
cursor: pointer;
font-size: 13px;
padding: 2px;
border: 1px solid black;
border-bottom-left-radius: 5px;
border-top-left-radius: 5px;
transition: 0.5s;
}
.groupButton:hover {
width: 60px;
transition: 0.5s;
}
.onOffGroupButton, .onOffGroupButton.buttonOn {
border: 1px solid blue;
background-color: rgba(255, 255, 10, 0.3);
padding: 5px;
cursor: pointer;
border-radius: 5px;
color: black;
position: relative;
margin-left: auto;
margin-bottom: 10px;
width: 220px;
font-weight: bold;
text-align: center;
}
.onOffGroupButton.buttonOff {
border: 1px solid black;
background-color: rgba(8, 8, 8, 0.3);
padding: 5px;
cursor: pointer;
border-radius: 5px;
color: black;
position: relative;
margin-left: auto;
margin-bottom: 10px;
width: 220px;
font-weight: bold;
text-align: center;
}

View File

@@ -1,605 +0,0 @@
/* --- BigNewAnnotation --- */
.vjs-default-skin .vjs-big-new-annotation{
float: left;
cursor: pointer;
line-height: 1.6em;
margin: 3% 3% 3% 4%;
top: 41%;
width: 6em;
height: 6em;
background-color: rgba(7,40,50,.7);
border-radius: 6px;
border: 0.25em solid #ccc;
}
.vjs-default-skin .vjs-big-new-annotation div{
width: 100%;
height: 100%;
top: 0em;
font-weight: bold;
font-size: 600%;
padding-top: 0.32em;
}
.vjs-default-skin.vjs-fullscreen .vjs-big-new-annotation{
top: 68%;
width: 8em;
height: 8em;
}
.vjs-default-skin.vjs-fullscreen .vjs-big-new-annotation div{
font-size: 750%;
padding-top: 42%;
}
.vjs-default-skin .vjs-big-new-annotation div:hover {
-webkit-box-shadow: 0 0 1em rgba(255, 255, 255, 1);
-moz-box-shadow: 0 0 1em rgba(255, 255, 255, 1);
box-shadow: 0 0 1em rgba(255, 255, 255, 1);
}
div.video-js > div.vjs-big-new-annotation {
visibility:hidden;
opacity:0;
-webkit-transition: visibility 0s linear 1s,opacity 1s linear;
-moz-transition: visibility 0s linear 1s,opacity 1s linear;
-o-transition: visibility 0s linear 1s,opacity 1s linear;
transition:visibility 0s linear 1s,opacity 1s linear;
}
div.video-js:hover > div.vjs-big-new-annotation {
visibility:visible;
opacity:1;
transition-delay:0s;
}
.vjs-default-skin .vjs-big-new-annotation.ul{
top:0%;
}
.vjs-default-skin .vjs-big-new-annotation.ur{
top:0%;
float:right;
}
.vjs-default-skin .vjs-big-new-annotation.br{
float:right;
}
.vjs-default-skin .vjs-big-new-annotation.c{
top:24%;
left:40%;
}
div.video-js:hover > div.vjs-big-new-annotation.none {
visibility:hidden;
}
.vjs-default-skin.vjs-fullscreen .vjs-big-new-annotation.c{
top:35%;
}
/* --- ControlBar --> AnContainerButtons --- */
.vjs-default-skin .vjs-container-button-annotation{
width: 101px;
}
/* --- ControlBar --> AnContainerButtons --> ShowStatistics --- */
/* --- ControlBar --> AnContainerButtons --> NewAnnotation --- */
/* --- ControlBar --> AnContainerButtons --> ShowAnnotations --- */
.vjs-default-skin .vjs-statistics-annotation,
.vjs-default-skin .vjs-showannotations-annotation,
.vjs-default-skin .vjs-new-annotation{
float: right;
cursor: pointer;
line-height: 1.6em;
background-position: left top;
margin: 4px;
width: 23px;
height: 21px;
background-repeat: no-repeat;
}
.vjs-default-skin .vjs-statistics-annotation.active,
.vjs-default-skin .vjs-showannotations-annotation.active,
.vjs-default-skin .vjs-statistics-annotation:hover,
.vjs-default-skin .vjs-showannotations-annotation:hover,
.vjs-default-skin .vjs-new-annotation:hover {
background-position: center top;
}
.vjs-default-skin .vjs-statistics-annotation:active,
.vjs-default-skin .vjs-showannotations-annotation:active,
.vjs-default-skin .vjs-new-annotation:active {
background-position: center right;
}
.vjs-default-skin .vjs-new-annotation {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEUAAAAVCAYAAAAQAyPeAAAABmJLR0QA/wDoAACU1v3rAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QgdAg4VAK182QAACfBJREFUWMOtmHtwVNUdxz/n3LubF4tAMAYEIYC8UiGOaAvYlwUqSqO042MQZgRsZ5R2pr5QW6d2FGEc6VhqLdQiDHQKRpniFBUd0JHUimSAmFB5CAQkD8mDJLvZ5733nNM/drMPgmgNZ+Y32fnt/r4553t+zyMAXlyzZuTw4cPXBwKBOVJKvukyxhCJRo81NzUteGnt2rrDhw+r6ZUvjLy8ZPj6/ILAbIEQ3xgbg5OIHmtrbV5Qv2ddXbj7iLo3f+bIsitGrx9cPGS2FPKbYQswRhMKho6dbD25YEe0vk48t2rV5ZMmT66fNXt2qVYKbQz9Wfn5eRw8cNDZu3fvjM3vRM6MLptcf911N5eG435UP6AFECgyNJ6qcQ7V750xdMcrZ26cPLP+/p/fX5rfbRD9ADcSKM5j+/tvOjvf3TnDHjx48NqpFVNL4/E4l2L19LiMnzDBf6qhYduAQNeBsVdPK+3o8YPpP3ZHl6D4iqn+gYNObbuycNiBW+fcUpp31sVg+g/f5DJ76nf9dTW122wp5cySkhLC4QiXatm2jTFmtETmFwauojPoXTJsRxVhtBkthcwvHz6BeHvwkmEHTD7CmNG2EEIkEgk8L3fjUkoGDBhwUZBIJIIQoo+twWBZFsJCxB3wVK6d8jxamo5iLhKqJcPGIBDk5RfmhpEAaUlsv18Qc9AqF9xTHseaG748DRjD2NJRCKAwvzDHx4wr8fn92Fpr4SkP13VzCKmurmbx4iU4jvOl3rBlyxaOHj3CwoUL+yRcrTVGK+EpyObMICkr/oKXn6y4KOGr/naW4cVxPqgz2P6idPgJAUZrAKGURns6s28EZ0cqrv/j0otin/lDNW6pD++jIEW+gjS2khow2EoblKdybjsQCPDggw+xdesWZs2ahTrvNgCUUixcuIj9+/cTDAZZtmxZBkOANgatFZ4CNysJRuOKJ34zgrWvO9SdFFyoZjiJbh5eOJRJY2wKC5t540MfPp8vCS0NymgMYDyV4yk65lH20E2ENxzCHO6CCxTSYCJC6bIb8I8v5kxRLfY7bfjsJLZWEgNIo5OEnC/RaJSSkhIaGxtpaWnJkcOHj/DAA8t45pmnmTJlCrW1nxAOhzP2rodWCqMVriJHHA+ktDh8WtMThWAkI6GoJBZpZ9FcwUuvtnHmrOHb1w7H7/flYBitQILyVFJUSlwPW9okjp9DhRN4PSkJJdA9Dm3RLuw7x9K0fh+6KcyI68dh+ey0vfYUCLCV1ijl5XiK53kIIXAcB611DtNaa1avfp6KigqWL1/O+vXrKSgooKOjI8dTVDJ8UAqyHa03vxidDKvsziURbuaJpYM43RLn/jsK+e1fwrieD4SVsZep8BEmeRCV2Z9JhZLWBjydrOOp1RLrZNivZxJr6mTQ4qmcfbYa2xVYIuNOyfABqbVGa51hOyUgyP5Oa000GuWxxx5n8uRyNmzYSCAwEKUUjz66HL/fn2FcJe2M0cnb9ZJkZOcXT2fplMCNtfL7B4ZyuiXObTcVY/kG0tkVY8ktISIxkWOvtQIh0J5GeyotKsW4UQrteWl9m9PFyMd/QLSxk9K55QywC4h0hnAXjEJHnSwMDyPA1lrjeW5OonVdByHAdTP61tZWqqqqmDFjOps2baaiooJVq1aybds2Dhw4gFIq/VuBSRHqEXMgloEmmsrbcTelN5ohBa0s/NlA6o4GmT9rKEc+hxUbFbNmXMb0CsnKLYZeZ/ObXlIgEewhHsy0EjrsIIBETxRCMYwxdBVrShdcy7n6M1xZOZX4kXa6V3/MoBtHM/D6Mlqfr0UUJHOK7bfBGGxtDK7j4mZVGSfhgBB4blJ/7tw5Nm3azNhx41i37q/MmTOHRx95mGB3N36fLxlqiUQGw+h0+HSGIRjOJNpQ6gzdUUNHyDAo7yxL7ynmdFOERT8p5d+fePzuFY+EK5gcNihjOBeGeMrDfL6kJwgJXZ81EwtlSFGhOKOAnlOtqOYeOodqJi27leDpNsbeeyPBD07S9PhOiCkGjMgjoDRdx5qQRf4kKT4brRVSK52Oa0FOGKY61B6eXbkKn8/H1q1bueuuu/jVL5fR3d2NEBkLIUTaXgiB0bq3dCYrBX2b2kB+mD89MgStHe6+uZi3PnJ57h/JcMpu7znP3uhk9ZEKhEr+lQpkb0rT4AyQXLPublytKLvnO3S+8SmtT72PjBuESv4GQHgZe5FyR1spBUIisgZBISUYg5CSuvpDHD9+nBMnTlBZWcn8+bfjuC7SskAI0nOYENCLISRaK7T2+hBhso47/VuSiWUBJpbBrhqPl3cIOntMshe5oE3yszYeSJBuhojeA0JSN3BmGUMmjYBJI+h++yidL+xDt0WTl6czBEgvyy51q7bWCikEMqsMSCEwxpCfl0fNvn3MmzePefPmMf7qcSQSiXRFEkJgSQutdQ6GFKCURhv1JXOxIBaL8cNpA9lTB+/thz2fSOIOyFShEUbguUGEKOwzGPZ6oKXBUn1JcaIxRs2aRHRXA+G3PiO8qwEr5mL1VjFj8BIOQghsL0OQJZP4tlIaKUUqFDId6ZgxY3i16jXuuPMObMsiFOqhpqamzyiw+73dlJeXY4xJY0gpMUZjLtD0WRLOBQ2LZkfY/m4zsbhGacWYy85rDrXh5huu4lijQApzXlugMBJsV2K7mX1rY+G1Rcj7RQX1VdWoaAKlNEwUQKasG62ZNH8C7n87sI2FSGHYyN7qoxBSkv2OEovF2LhxA3Pm/JiqqqqLvp/MnTuXFc88TSgUSmNIKdHaoE1fUooK4L7nFNtXjmDhvBEXbcdrjhiWr3UpyDv//yZ7EEsJ7Kz8Q0EerZWvMf7jxYy/73sXxY59eIb2xW/i8/voLW22FMnwiUSjEWNM2vVN6lAYw8kTx3NyzYWfCnr4oqUFy7LAJMcrIQWRaNRTTiTik31np+Z2Q/kih696urEt+hBiWx6eE/biyoloabC988pDQw+NBau/+n3GlliFNplZwCB8goSXwG5v73jl4MHaFeXl16CUyqk+JxsavtbILS0rKzwE4XCYUCj0djzSXtPTuH2Fb/BPcT2TM+kOKPj/R3spBXnqc7xE8O0uFa7ZrQ6tmCMnYFydm3WK8r8eYHY+kpKW/AiRiPsvq7a29vDIkSMnWpIJJVeU9vtN4vSpBvbsqT6+Zs2LS8821lUXBQZNLLTCE1RB+QXe0r6+WNKiILKL9pOvHz/ynz8v/TTcVF1cEJjoFDJhXHxov/e9b3ATOxIHjq9t2blUAMVA0W2VlUumTZv2VH/BT5w4sXnbtn+ujETDnYAGikZc/f0lV46/td/YXqLtaO3u1bdrSGP/6PIpS8blD3tSC21JIdDGIIxAyOSkntYhMOR+l9YhTLsb/PsbHftWGpfO/wH+lr/CdYGcQQAAAABJRU5ErkJggg==');
}
.vjs-default-skin .vjs-showannotations-annotation {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEUAAAAVCAYAAAAQAyPeAAAABmJLR0QA/wDoAACU1v3rAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QgdAgcPLA0+6gAABatJREFUWMOtmN9vFFUUx7/nzuyyUNdQCqUUa0oEyo9ETOBFfuiDlvAjATXxhfhgIMbgP2BCjL5BSEwMQYMm4AMaXmxABSkGogHUKgk0LeF3AQMtAq2FbXeX3Zl7zvFhtmuXdsrsLjeZzOTePZ8998w533vvEADs3rWrqbGxcW8ymVxtjEGlTVWRyWav9PX2bvpiz56uixcv8ssbPmuaUd+4NzE52UogqpgNhZfPXrl/r29T98kvu9IPL/G7iRVNc2Y2762tm9ZqyFTGJkBVMJQaunL93vVNh7PdXbRzx44ZCxct6n69tbVBmCGqqKYlEpNw7uw5r6OjY/n+Y5lbzXMWdS9duqYhnYuDq0ATgGSN4vbNM9757o7l0w/vu7Vy0Yrure9tbUg8VFAVcDUA6ibh0C9HvPaf25e7tbW1e5a8tKQhl8vhabThYR/zW1riN2/caHsm+eDsC/OWNQwMxwGtnj3wgFA3c0n82ak322ZPmXV2/ep1DZPu+lBo9fheH61LVsW7znS2ucaYFfX19UinMwCAlgULI3OuXL40br/rulDVZgOTmJJ8HoMpCwA4sHNWZPamD/8Zt9/jGqhosyGTWNzYglx/CgAw++uNkdl9m38Ytz+pCZBqs0tElM/nYa0tDv57YeCJ4LrF00tsHq9/x3FADijnAZZRPptDyogA4xi48TjhkQdhLps92qbEb98gFo/DFRGybOH7ftkZF2ajqhARqDBZBkJiN2ELsyECVAQAiFkgVspmh9mwEQAKl0XBlkveet3i6REdt6GqKKoQYVgG/FEiGJXthwgnGQWrQAGo5ZK3HpUdlinCBgrAVQkCMjLBPzv+KONt2gn/WIXhM+AXfFjzwZ3oWRhWPgZQYcAAbBlsGSCg5+0DgZhTsYbHPhfuzFw6XmjGGoAAl0XAbEMnuHLVK5En8tvpU8VM4aB8wAyEvBgc/6oxMrv1/SCg1hTKhxTMDOHxS2H+oXcis6+++e2o8gFcEYGIBNELaVEFbIRhjAk0RSXIFIvitk0VJVu4coWXCBBhgAhiBWKr93uEIYagVAiKtX5FQhsmvIRAaEUsHnnAo+rRyHrBPa4jQQHyqWHkUpmq2blUOsiQuAuowhVV+J4P3/MmjGakoIwwVIrlM5gGUmmtmj1YYMRigDKDDPDgah8eDWWqZj+81hcEJeZChOEKSzGdaawmof2nI+P2j77jMc0iIqjIyNIZutuc+1ZfGWefUc8SrD6GAeLxtfVk/bYwnR3zW/D/Ig4ALjMDZECFg+DatesiO3qs/SgoZIkQYYjYksn0HJwdmR0WMAUgagEDGB8whfVh1eD2yOzT07aN67ehIFKuCMMQwYxSv6gCZUIOvYYAZoEojzkXR2VPdDAcyUBHAKeC3bITos1OsCLDZRYYQ6AKTvVhNsYYqAp0ghWtmibCUAO4voHrl+93mI0LM7L6MMgYjP6OElWgwr69BEuyQpQrFr+Jv9sIQIDDBJepbPZom5J+Q0H5ZLLZjKoWS+HXE8crd7YoKYRMNmvZy2RixqtIWEMn5FhYL21z7GXEKFwbCEG38zEib2ntGKkFoKAYIW/zMP39A/vOneuEG4+DHKeqyzgO3JiLdDqNoaGho7lM/77h24cQc+mplI0xhEl8CzafOvqA0/tO8HnEjAu3kDEumyc8h40TYurgfiKDDPwfnc7OzotNTU0LHIOW+pkNVTv+980bOHny1LVdu3ZvuXu761RNcuqCKU66hScvHkcyo1+OcTA5cxz917+7dun3z7dcSPeeqpucXOBNQcvcXPUl+VdtLw7nz17bc6d9CwGoA1CzccOGzcuWLfukWnhPT8/+traD2zPZ9CAAAVDz3LxXN8+ev75qts3fv9x54tM3BCiyX5vx4ua5iVkfCYljiCCqICWQCU7qxT4QFKVjxT6Q9vupb74f+Gu7+hj8D6dPKX8nggZiAAAAAElFTkSuQmCC');
}
.vjs-default-skin .vjs-statistics-annotation {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEUAAAAVCAYAAAAQAyPeAAAABmJLR0QA/wDoAACU1v3rAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QgdAhEHPk4DDwAABcNJREFUWMOtV21oHOcRfmb2vfPZyoWoimVFjhKFfMh1oC7EUGo3hDRRCAkopT/6w5DEtWkhkNISSH8VTP849IMW4QSHYkMikz+pyIcd7IQEBxtS44AtpBAnjr9aWwq2ZWSfdHe+292Z6Y+TTnvWrk+n9QvLDs++M8zOO/PMvAQAOwYHe7q7u3fl8/mnmBlLXWaGUrl8cmJ8fNMbO3eOnjhxQn468M+elZ3du3LL8/0EoiXbhsGvlk9evjSxaezQm6PFa9/I5tzGnvtW9e5q7/hBPxMvzTYBZorpwvTJM5fObNpXHhulv7z22sofrl079mR/f5eKQM2QZuVyy3D82HH/yJEjG4Y+Lp3vvW/t2COPPN1VrGQhKUwTgHyb4cK5L/2vxo5suHPf7vM/W7tx7KXfvNSVu2agFMaNAXQsw/sHP/IPfHJgg2tvb9+57sfruiqVCm7FmpkJ8FBfX/bc2bPDt+WvHrv/wfVdV2aygKW3feUqoWPVuuztd5wbXr3irmPPPvVM17KLAQyW3vx4gP51j2ZHvxwZdsy8sbOzE8ViqWU7jz/+87r8+ecH67JzDmbWy+Dcivw9mCqELdve8aqry7/727y+L20wtV4mzj3c3YfKZKH1bP7rhrpc+eN/6nLeciCzXkdEVK1WEYZhqkBH9Q0Gz/NAHqjiA6GkO8SoPhHAHsNls4TrPlTSGY/qW8DIZLNwqkqhhAiCIJXxqL6ZQVVhKhQKkDLeDfpEgKkCAIkoNNR0QYnoCysAgxM1SCgNJz0w8Fxd3rv3w5YzBQSoGVQFoQBBhATf2papy5v/vLiDiOoTG8QUBsBCaTjp21+fL+fplw+2nCkqDAPgTGsBSSqfxZbVjftUBKaCQIBAkn52kVkYLR8GTAVgQEKBhFJrTTesBtxm29fcO7ovEhQOGSDAiSpEbnFQCJBa+UAESCr7xdJBdF/Is+VDBhGBiiZkgC6xfACnqlDVhoglRfLmjkcizlzjFNNapoSIHduiuFmjfDOiVRWACBoqNIHFdZHsHt2nTDCaDUoYBolEO4e/8MKLdWxo6O2bEi2hRrSqIa77wPUE6pjD9/9jnmeeeWXh5rI/L2dtLihAtTCDSiF+lKgUigCAnvd+Vccu/PLdxH0A4LIOMINTMwR+gMD344MSgzfFTOvlM1UECsX40WoqBm+GZTKAiYAYuPrdBK5PzwelJ6Jz7dRESxgAuIyDqsCpaD1tKWG8jsPsJvuICKY61zoTp01bImZa6z4sAEmCjzF4HMY3kDgAOBEBiEFJF8E4nHmhI9F9xFAVqIa3YrpfECC1EGCAA4AT+kAcHodRBGOqna5TFTAROOECG4c3w5gAEYWapLgXJ18M5zLQU8BL4NM4vBnm1ToynIiCmUAJ3sfhzTBmhpnCUo7giR1DBcaACxguiPc7Dm+GOfBc9xEQM5gZz0c6zNx6cfOvW8L2DL0925INavNBOfqv7AKdVrGf/NafbdkKEOAJwQnh3onfL9C5//wfWsL+t3oQjqlWPqVyuWRmYCK8s2eoYehLktGEOIkJpXI5FL9UyrDf8ENpl/NChH4xrIhfUja4kDCxakcTj28caReOuA4EyhCqYRU8OXll9/HjI3DZLMjzwJ4Hmn2S5KSHPQ8u41AsFjE9Pb2/UprcPXPhfWTcrSEWZsIyOY+wWth/VYq7P5OvkGEHN5sxTriJnPQmZMzD5VwJJQR7vZGRkRM9PT1rPEZf56qu1I7/99xZHDp0+NTg4I6tFy+MHm7L37FmhVfsk+UPx1Dm4h+PPSwvfYrJM/8+9c0Xr2/9ujh+uGN5fo2/An0PVO5M7ffR9nHsqx47tfP7A1sJQAeAtucGBrasX79+W1rjp0+fHhoefm97qVycAqAA2u5+8LEtqx96NrXtsHr525HP/v4LBeq2n1j5oy0P5O76k5J6TAQ1AxmBuHZTr2MgGBq/1TGQTQaFPR9cObrdAkz9Hw14UPPRoMvjAAAAAElFTkSuQmCC');
}
/* --- ControlBar --> BackAnDisplay --- */
.vjs-default-skin .vjs-back-anpanel-annotation{
float: left;
left: 0em;
right: 0em;
position:absolute;
background-color: rgba(0,0,0,0.3);
width: auto;
/*font-size: .3em;*/
font-size: .9em;
-webkit-transition: top .4s,height .4s,font-size .4s,-webkit-transform .4s;
-moz-transition: top .4s,height .4s,font-size .4s,-moz-transform .4s;
-o-transition: top .4s,height .4s,font-size .4s,-o-transform .4s;
transition: top .4s,height .4s,font-size .4s,transform .4s;
opacity:1;
visibility:visible;
transition-delay:0s;
}
/* --- ControlBar --> BackAnDisplay --> RangeSelectorDisplay --- */
.vjs-default-skin .vjs-rangeselector-anpanel-annotation{
height: 100%;
width: 100%;
position: absolute;
top: -1em;
}
.vjs-default-skin .vjs-back-anpanel-annotation.statistics .vjs-rangeselector-anpanel-annotation{
z-index:2;
}
/* RangeSelectorLeft */
.vjs-default-skin .vjs-leftselector-anpanel-annotation{
height: 100%;
margin-top: 1em;
width:0%;
float:left;
position:absolute;
left: 0%;
}
.vjs-default-skin .vjs-leftselector-anpanel-annotation .vjs-selector-arrow{
z-index:10;
border-left: 1em solid #FFE800;
cursor: e-resize;
}
.vjs-default-skin .vjs-leftselector-anpanel-annotation .vjs-leftselector-back{
right:100%;
border-right: 1px dashed #FFE800;
}
.vjs-default-skin .vjs-leftselector-anpanel-annotation.include .vjs-leftselector-back{
border-right: 1px dashed rgb(255, 163, 0);
}
.vjs-default-skin .vjs-leftselector-anpanel-annotation.include .vjs-selector-arrow{
border-left: 1em solid rgb(255, 163, 0);
}
/* RangeSelectorRight */
.vjs-default-skin .vjs-rightselector-anpanel-annotation{
height: 100%;
margin-top: 1em;
width:100%;
float:right;
position:absolute;
}
.vjs-default-skin .vjs-rightselector-anpanel-annotation .vjs-selector-arrow{
z-index:20;
border-right: 1em solid #FFE800;
margin-left: -1em;
cursor: w-resize;
}
.vjs-default-skin .vjs-rightselector-anpanel-annotation .vjs-rightselector-back{
border-left: 1px dashed #FFE800;
}
.vjs-default-skin .vjs-rightselector-anpanel-annotation.include .vjs-rightselector-back{
border-left: 1px dashed rgb(255, 163, 0);
}
.vjs-default-skin .vjs-rightselector-anpanel-annotation.include .vjs-selector-arrow{
border-right: 1em solid rgb(255, 163, 0);
}
.vjs-default-skin .vjs-leftselector-back,
.vjs-default-skin .vjs-rightselector-back{
height: 100%;
width: 100%;
position:absolute;
background-color: rgba(0,0,0,0.6);
}
.vjs-default-skin .vjs-selector-arrow{
width: 0;
height: 0;
border-top: 1em solid transparent;
border-bottom: 1em solid transparent;
opacity: 0.8;
position: absolute;
top: -2em;
}
/* RangeSelectorBar */
.vjs-default-skin .vjs-barselector-anpanel-annotation{
height: 2em;
margin-top: -1em;
background-color: rgba(0,0,0,0.6);
border: 1px solid rgba(255,255,255,0.6);
position: absolute;
float: left;
visibility:visible;
transition-delay:0s;
}
.vjs-default-skin .vjs-barselector-anpanel-annotation.disable{
visibility:hidden;
opacity:0;
-webkit-transition: visibility 0.5s linear 0.5s,opacity 0.5s linear;
-moz-transition: visibility 0.5s linear 0.5s,opacity 0.5s linear;
-o-transition: visibility 0.5s linear 0.5s,opacity 0.5s linear;
transition:visibility 0.5s linear 0.5s,opacity 0.5s linear;
}
.vjs-default-skin .vjs-barselector-anpanel-annotation .vjs-barselector-left{
float: left;
left: 1em;
}
.vjs-default-skin .vjs-barselector-anpanel-annotation .vjs-barselector-right{
right: 1em;
float: right;
}
.vjs-default-skin .vjs-barselector-anpanel-annotation .vjs-barselector-right,
.vjs-default-skin .vjs-barselector-anpanel-annotation .vjs-barselector-left{
height: 2em;
font-size: 1.3em;
position: absolute;
}
.vjs-default-skin .vjs-rangeselector-anpanel-annotation.active .vjs-barselector-anpanel-annotation{
z-index: 1;
}
/* --- ControlBar --> BackAnDisplay --> AnDisplay --- */
.vjs-default-skin .vjs-anpanel-annotation{
float: left;
width: 100%;
height: 100%;
left: 0em;
right: 0em;
position:absolute;
/*background-color: #FFE800;
background: #FFE800;
background: -moz-linear-gradient(top, #FFE800, #A69700);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#FFE800), to(#A69700));
background: -webkit-linear-gradient(top, #FFE800, #A69700);
background: -o-linear-gradient(top, #FFE800, #A69700);
background: -ms-linear-gradient(top, #FFE800, #A69700);
background: linear-gradient(top, #FFE800, #A69700);*/
opacity: 0.8;
overflow: hidden;
}
.vjs-default-skin .vjs-anpanel-annotation .annotation{
height: 1em;
float: left;
width: 100%;
left: 0em;
right: 0em;
cursor:pointer;
position:absolute;
background-color: #FFE800;
background: #FFE800;
background: -moz-linear-gradient(top, #FFE800, #A69700);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#FFE800), to(#A69700));
background: -webkit-linear-gradient(top, #FFE800, #A69700);
background: -o-linear-gradient(top, #FFE800, #A69700);
background: -ms-linear-gradient(top, #FFE800, #A69700);
background: linear-gradient(top, #FFE800, #A69700);
opacity: 0.8;
}
.vjs-default-skin .vjs-anpanel-annotation .annotation.active {
background-color: #2DCF02;
background: #2DCF02;
background: -moz-linear-gradient(top, #2DCF02, #114F01);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#2DCF02), to(#114F01));
background: -webkit-linear-gradient(top, #2DCF02, #114F01);
background: -o-linear-gradient(top, #2DCF02, #114F01);
background: -ms-linear-gradient(top, #2DCF02, #114F01);
background: linear-gradient(top, #2DCF02, #114F01);
z-index: 1;
}
.vjs-default-skin .vjs-anpanel-annotation .annotation.point {
border-radius: 50%;
width: 1em;
height: 1em;
margin-left: -0.4em;
}
.vjs-default-skin .vjs-back-anpanel-annotation.statistics .vjs-anpanel-annotation{
visibility:hidden;
}
/* --- ControlBar --> BackAnDisplay --> AnStat --- */
.vjs-default-skin .vjs-anstat-annotation{
float: left;
width: 100%;
height: 100%;
left: 0em;
right: 0em;
position: absolute;
opacity: 0.8;
visibility:visible;
transition-delay:0s;
font-size: 1.2em;
}
.vjs-default-skin .vjs-anstat-annotation.disable{
visibility:hidden;
opacity:0;
}
.vjs-default-skin .vjs-totan-anstat-annotation,
.vjs-default-skin .vjs-maxcon-anstat-annotation{
position: absolute;
top: 0.3em;
background-color: rgba(0,0,0,0.5);
border-radius: 0.5em;
padding: 0.1em;
color: rgb(255, 163, 0);
}
.vjs-default-skin .vjs-totan-anstat-annotation{
float: right;
right:1em;
}
.vjs-default-skin .vjs-maxcon-anstat-annotation{
float: left;
left:1em;
}
/* --- ControlBar --> BackAnDisplay --> --- */
.vjs-default-skin .dashed-line{
float: left;
right: 0em;
position:absolute;
color: #2DCF02;
border-left:0.23em dashed #2DCF02;
border-right:0.23em dashed #2DCF02;
opacity: 0.8;
}
.vjs-default-skin .dashed-line.point{
border-right:0;
}
.vjs-default-skin .box-dashed-line{
height: 1em;
float: left;
right: 0em;
color: #2DCF02;
position:absolute;
background-color:#2DCF02;
opacity: 0.8;
}
.vjs-default-skin .boxup-dashed-line{
height: 1em;
float: left;
right: 0em;
color: #2DCF02;
position:absolute;
opacity: 0.8;
background-color: #2DCF02;
background: #2DCF02;
background: -moz-linear-gradient(top, #2DCF02, #114F01);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#2DCF02), to(#114F01));
background: -webkit-linear-gradient(top, #2DCF02, #114F01);
background: -o-linear-gradient(top, #2DCF02, #114F01);
background: -ms-linear-gradient(top, #2DCF02, #114F01);
background: linear-gradient(top, #2DCF02, #114F01);
z-index: 4;
-webkit-transition: top 1s,-webkit-transform .4s;
-moz-transition: top 1s,-moz-transform .4s;
-o-transition: top 1s,-o-transform .4s;
transition: top 1s,transform .4s;
}
.vjs-default-skin .boxup-dashed-line.point{
border-radius: 50%;
width: 1em;
height: 1em;
margin-left: -0.4em;
}
/* --- ControlBar --> BackAnDisplay --> BackAnDisplayScroll --- */
.vjs-default-skin .vjs-down-scroll-annotation,
.vjs-default-skin .vjs-up-scroll-annotation{
width:2em;
height:2em;
float: left;
right: 0em;
position:absolute;
cursor: pointer;
border-left: 1em solid transparent;
border-right: 1em solid transparent;
/*font-size: .3em;*/
font-size: .9em;
-webkit-transition: top .4s,height .4s,font-size .4s,-webkit-transform .4s;
-moz-transition: top .4s,height .4s,font-size .4s,-moz-transform .4s;
-o-transition: top .4s,height .4s,font-size .4s,-o-transform .4s;
transition: top .4s,height .4s,font-size .4s,transform .4s;
opacity: 0.8;
transition-delay:0s;
}
.vjs-default-skin .vjs-up-scroll-annotation{
border-bottom: 1em solid black;
}
.vjs-default-skin .vjs-down-scroll-annotation{
top: -3em;
border-top: 1em solid black;
}
.vjs-default-skin .vjs-scroll-anpanel-annotation.disable,
.vjs-default-skin .vjs-back-anpanel-annotation.disable{
visibility:hidden;
opacity:0;
/*-webkit-transition: visibility 1s linear 1s,opacity 1s linear;
-moz-transition: visibility 1s linear 1s,opacity 1s linear;
-o-transition: visibility 1s linear 1s,opacity 1s linear;
transition:visibility 1s linear 1s,opacity 1s linear;*/
}
.vjs-default-skin:hover .vjs-back-anpanel-annotation,
.vjs-default-skin:hover .vjs-down-scroll-annotation,
.vjs-default-skin:hover .vjs-up-scroll-annotation {
font-size: .9em;
-webkit-transition: top .2s,height .2s,font-size .2s,-webkit-transform .2s;
-moz-transition: top .2s,height .2s,font-size .2s,-moz-transform .2s;
-o-transition: top .2s,height .2s,font-size .2s,-o-transform .2s;
transition: top .2s,height .2s,font-size .2s,transform .2s;
}
/* --- ControlBar --> BackAnDisplay --> BackAnDisplayScroll--> BackAnDisplayScrollBar --- */
.vjs-default-skin .vjs-scrollbar-anpanel-annotation{
float: left;
position: absolute;
cursor: pointer;
right: 0.5em;
width: 1em;
/*font-size: .3em;*/
font-size: .9em;
background-color: black;
opacity: 0.8;
visibility:visible;
transition-delay:0s;
-webkit-transition: top .4s,height .4s,font-size .4s,-webkit-transform .4s;
-moz-transition: top .4s,height .4s,font-size .4s,-moz-transform .4s;
-o-transition: top .4s,height .4s,font-size .4s,-o-transform .4s;
transition: top .4s,height .4s,font-size .4s,transform .4s;
}
.vjs-default-skin .vjs-scrollbar-anpanel-annotation.disable{
visibility:hidden;
opacity:0;
-webkit-transition: visibility 1s linear 1s,opacity 1s linear;
-moz-transition: visibility 1s linear 1s,opacity 1s linear;
-o-transition: visibility 1s linear 1s,opacity 1s linear;
transition:visibility 1s linear 1s,opacity 1s linear;
}
.vjs-default-skin .vjs-scrollbar-anpanel-annotation:hover{
opacity: 0.8;
visibility:visible;
transition-delay:0s;
}
.vjs-default-skin:hover .vjs-scrollbar-anpanel-annotation{
font-size: .9em;
}
.vjs-default-skin .vjs-scrollbar-selector{
width: 1em;
background-color: gray;
border: 1px solid black;
position:absolute;
height: 3em;
border-radius: 0.4em;
}
/* --- ControlBar --> BackAnDisplay --> BackAnDisplayScroll--> BackAnDisplayScrollTime --- */
.vjs-default-skin .vjs-down-scrolltime-annotation,
.vjs-default-skin .vjs-up-scrolltime-annotation{
width: 100%;
height:1em;
float: left;
position:absolute;
font-size: .9em;
opacity: 0.8;
transition-delay:0s;
right: 3em;
text-align: right;
margin-top:0.2em;
}
.vjs-default-skin .vjs-down-scrolltime-annotation{
top: -2.6em;
margin-top: -0.2em;
}
.vjs-default-skin .vjs-scrolltime-anpanel-annotation span{
font-size: 1.3em;
background-color: rgba(0,0,0,1);
border-radius: 0.5em;
padding: 0.1em;
border: 0.1em solid white;
padding-left: 0.4em;
padding-right: 0.4em;
}
/* ---------------- Modify the CSS of Annotator plugin ---------------- */
.annotator-wrapper.vjs-fullscreen .annotator-adder,
.annotator-wrapper.vjs-fullscreen .annotator-outer,
.annotator-wrapper.vjs-fullscreen .annotator-widget,
.annotator-wrapper.vjs-fullscreen .annotator-notice {
z-index:3000000000; /*To fix full-screen*/
}
/* ---------------- Modify the CSS of Video-js plugin ---------------- */
.vjs-default-skin *, .vjs-default-skin *:before, .vjs-default-skin *:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
/* ---------------- Modify the CSS of Range Slider plugin ---------------- */
/* Selection bar in green color */
.vjs-default-skin .vjs-rangeslider-holder.locked span.annotator-hl > div.vjs-selectionbar-RS {
background-color: #2DCF02;
background: #2DCF02;
background: -moz-linear-gradient(top, #2DCF02, #114F01);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#2DCF02), to(#114F01));
background: -webkit-linear-gradient(top, #2DCF02, #114F01);
background: -o-linear-gradient(top, #2DCF02, #114F01);
background: -ms-linear-gradient(top, #2DCF02, #114F01);
background: linear-gradient(top, #2DCF02, #114F01);
}
.vjs-default-skin div.vjs-rangeslider-holder.locked .vjs-rangeslider-handle > div.vjs-selectionbar-line-RS {
background-color: #2DCF02;
}
.vjs-default-skin div.vjs-rangeslider-holder.locked .vjs-rangeslider-handle > div.vjs-selectionbar-arrow-RS {
border-top-color: #2DCF02;
}

View File

@@ -1,186 +0,0 @@
/*Range Slider Bar Time*/
.vjs-default-skin .vjs-timebar-RS{
color: red;
top: -1em;
height: 100%;
position: relative;
background: rgba(100,100,100,.5);/*Quitar*/
}
/*Selection Range Slider Bar Selected*/
.vjs-default-skin .vjs-rangeslider-holder{height: 100%;}
.vjs-default-skin .vjs-selectionbar-RS{
height: 100%;
float: left;
width: 100%;
left: 0em;
right: 0em;
position:absolute;
background-color: #FFE800;
background: #FFE800;
background: -moz-linear-gradient(top, #FFE800, #A69700);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#FFE800), to(#A69700));
background: -webkit-linear-gradient(top, #FFE800, #A69700);
background: -o-linear-gradient(top, #FFE800, #A69700);
background: -ms-linear-gradient(top, #FFE800, #A69700);
background: linear-gradient(top, #FFE800, #A69700);
opacity: 0.8;
}
.vjs-default-skin div.vjs-rangeslider-holder.locked > div.vjs-selectionbar-RS {
background-color: #FF6565;
background: #FF6565;
background: -moz-linear-gradient(top, #FF6565, #300000);
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#FF6565), to(#300000));
background: -webkit-linear-gradient(top, #FF6565, #300000);
background: -o-linear-gradient(top, #FF6565, #300000);
background: -ms-linear-gradient(top, #FF6565, #300000);
background: linear-gradient(top, #FF6565, #300000);
}
/*Arrow and Handle*/
.vjs-default-skin div.vjs-rangeslider-handle {
position: absolute;
margin-top: 0;
cursor: pointer !important;
background-color: transparent;
}
.vjs-default-skin .vjs-selectionbar-left-RS{height: 100%;left: 0;z-index:10}
.vjs-default-skin .vjs-selectionbar-right-RS{height: 100%;left: 100%;z-index:20}
.vjs-default-skin div.vjs-selectionbar-left-RS,
.vjs-default-skin div.vjs-selectionbar-right-RS {
top: 0em;
position: absolute;
width:0em;
}
.vjs-default-skin div.vjs-selectionbar-arrow-RS {
width: 0;
height: 0;
border-left: 1em solid transparent;
border-right: 1em solid transparent;
border-top: 1em solid #FFF273;
margin-left: -1em;
opacity: 0.8;
position: absolute;
top: -1em;
}
.vjs-default-skin div.vjs-rangeslider-handle.active > div.vjs-selectionbar-arrow-RS {
border-top-color: #5F5FB3;
}
.vjs-default-skin div.vjs-rangeslider-holder.locked .vjs-rangeslider-handle > div.vjs-selectionbar-arrow-RS {
border-top-color: #FF6565;
}
.vjs-default-skin div.vjs-selectionbar-line-RS {
width: 1px;
height: 1em;
background-color: #FFF273;
position:absolute;
top: 0em;
}
.vjs-default-skin div.vjs-rangeslider-handle.active > div.vjs-selectionbar-line-RS {
background-color: #5F5FB3;
}
.vjs-default-skin div.vjs-rangeslider-holder.locked .vjs-rangeslider-handle > div.vjs-selectionbar-line-RS {
background-color: #FF6565;
}
/* Time Panel */
.vjs-default-skin .vjs-timepanel-RS{
width: 100%;
height: 1em;
font-weight: bold;
font-size: 15px;
top: -2em;
position: absolute;
visibility:visible;
opacity:1;
transition-delay:0s;
}
.vjs-default-skin .vjs-timepanel-RS.disable{
visibility:hidden;
opacity:0;
-webkit-transition: visibility 1s linear 1s,opacity 1s linear;
-moz-transition: visibility 1s linear 1s,opacity 1s linear;
-o-transition: visibility 1s linear 1s,opacity 1s linear;
transition:visibility 1s linear 1s,opacity 1s linear;
}
.vjs-default-skin .vjs-timepanel-left-RS,
.vjs-default-skin .vjs-timepanel-right-RS{
font-weight: normal;
font-size: 1em;
color: #666666;
border: 1px solid #666666;
background-color: white;
border-radius: 5px;
position: absolute;
height:116%;
padding-right: 0.3em;
padding-left: 0.3em;
}
.vjs-default-skin .vjs-timepanel-left-RS{
left:0.5%
}
.vjs-default-skin .vjs-timepanel-right-RS{
left:92%
}
/* Control Time Panel */
.vjs-default-skin .vjs-controltimepanel-RS{
width: 18em;
font-size: 1em;
line-height: 3em;
}
.vjs-default-skin .vjs-controltimepanel-RS input{
width: 1.5em;
background: rgba(102, 168, 204, 0.16);
border: 1px solid transparent;
color: black;
font-size: 1em;
margin-left: 2px;
text-align: center;
color: white;
}
.vjs-default-skin .vjs-controltimepanel-left-RS{
width: 50%;
float: left;
}
.vjs-default-skin .vjs-controltimepanel-right-RS{
float:right;
width: 48%;
}
.vjs-default-skin .vjs-controltimepanel-RS input{
margin: 0;
padding: 0;
display: table-cell;
}
/* ---------------- Video-js plugin ---------------- */
.vjs-default-skin *, .vjs-default-skin *:before, .vjs-default-skin *:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
margin: 0;
padding: 0;
}

View File

@@ -1,54 +0,0 @@
.annotator-viewer div:first-of-type.richText-annotation *,
.annotator-viewer div:first-of-type.richText-annotation{
font-style: normal;
font-weight: inherit;
text-align: inherit;
}
.annotator-viewer div:first-of-type.richText-annotation{
padding-top: 22px;
}
/* Fix in the tinymce */
.annotator-viewer div:first-of-type.richText-annotation strong{
font-weight: bold;
}
.annotator-viewer div:first-of-type.richText-annotation em{
font-style: italic;
}
.mce-floatpanel {
z-index: 700000000!important;
}
.annotator-wrapper .mce-container {
z-index: 3000000000!important; /*To fix full-screen problems*/
}
.mce-container-body {
min-width: 400px;
}
.iframe[id="annotator-field"] {
width: inherit;
min-width: 400px;
}
div.mce-tinymce.mce-container.mce-panel {
min-width:400px;
}
/* Some change in the design of Annotator */
.annotator-editor .annotator-widget{
min-width: 400px;
}
/*Rubric icon*/
.mce-ico.mce-i-rubric{
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QkBBB07nraNoQAAAhZJREFUKM+NkstrE1EUxr+5c08ykztpJtVoazHBF8FgQQzonyBKEZS6FrQKLl0EXBRT0ZULJSs3oii4TyHgu90IlTaL6qouWlv7Ck1N0BSnmZk714WbPHz07M4534+Pw3eAHdTY8A9+Nd9/bshU1DpnO4HXjh2ZY2J9/OSTxHTrnP8PvJYf+BDQ6qEDaQBB43jrTusUFy4oPjsYWYzF+VS91nxLYfdhKgONaQT3W/KMxr1XY5e+qj86f8zsKYYsZ6AvjWFzA8ORHkAnwN8So7evzL/8pzMAXL/Hq8mMv1up371T7Z+/c3n9cKeuDS6Xy6dN07zLuZ56Onk2Ed2/ANJsnE/PQMpgyffle+kYzwazB1+3waVS6X48Hr9BRPB9H57nYXplFKeSt8D1Hriug9XKF0x+Lmw+ys8m2m42DOOn4zhQSsGyLOi6jqONm9isbmFVFlDbaGKx8QaB1rvdlbNhGLAsC0IIGIYBIQSy2ROQ0oOp7wOPraHXEugRvDtnzjmi0SiICEIIEBGklAB9B6cmbG0AUnrY5m73h+m6DsYYTNMEYwxEBMY0hGNVhHkcZigBO9qHlDHS7cwYg23bAIBQKAQigud7IH0XwtxDoHwEIQ9SLKx0wa7rPiaivYyxESklXNeFBg0mjyNQTQSuATMSm6ipuYt//eVcLhdeXl5+UKlUlur1upqamVAv3j3/VCyOD3VqfwF6uLp3q+vMcgAAAABJRU5ErkJggg==');
background-repeat: no-repeat;
}
/* Fixes conflicting design between tinymce css and annotator css */
.mce-ico.mce-i-resize {
font-family: 'tinymce';
}

View File

@@ -1,205 +0,0 @@
/* Editor */
.share-container-annotator {
display: block;
min-width: 100%;
border: none;
margin: 0;
color: rgb(60, 60, 60);
background: none;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
resize: none;
padding-left: 0.6em;
padding-right: 1em;
height: 3.1em;
}
.share-container-annotator .share-text-annotator {
float:left;
padding-top: 1em;
}
.annotator-editor .share-container-annotator .share-text-annotator {
height: 2.1em;
}
.share-container-annotator .share-button, .annotator-wrapper .share-button {
top: 0.3em;
outline: 0;
float:left;
position: relative;
text-align: center;
margin: 0;
padding: 0;
margin-left:0.3em;
height: 2.5em;
width: 2.5em;
background-repeat: no-repeat;
background-size: 2.5em;
}
.share-container-annotator .share-button:hover, .annotator-wrapper .share-button:hover {
opacity: .6;
cursor: pointer;
}
/* Popup */
.annotator-wrapper .share-popup-overlay-bg {
display: none;
position: fixed;
top: 0;
left: 0;
height:100%;
width: 100%;
cursor: pointer;
background: #000; /* fallback */
background: rgba(0,0,0,0.75);
padding: 0;
}
.annotator-wrapper .share-popup-overlay-bg .share-popup {
background: #fff;
padding: 1% !important;
width: 30%;
position: relative;
top: 15%;
left: 50%;
margin: 0 0 0 -17% !important; /* add negative left margin for half the width to center the div */
cursor: default;
border-radius: 4px;
box-shadow: 0 0 5px rgba(0,0,0,0.9);
}
.annotator-wrapper .share-popup-overlay-bg .share-popup-copy,
.annotator-wrapper .share-popup-overlay-bg .share-popup-title {
font-style: normal;
font-weight: bold;
font-size: 21px;
padding-top: 0px;
padding-bottom: 20px;
color: #222;
}
.annotator-wrapper .share-popup-overlay-bg .share-popup-uri {
width:100%;
border: 1px solid rgb(144, 144, 144);
height: 24px;
margin-bottom: 10px;
}
.annotator-wrapper .share-popup-overlay-bg .share-popup-copy {
font-size: 15px;
float: left;
width: 100%;
padding:0;
margin: 1.0em 0em 0.5em 0em !important;
}
.annotator-wrapper .share-popup-overlay-bg .share-popup .share-button {
width: 50%;
padding: 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
border: 1px solid;
margin: 0;
text-align: center;
alignment-baseline: central;
background-position: 0.5em;
height: 4em;
padding-top: 1.3em !important;
}
/* Close button */
.annotator-wrapper .share-popup-overlay-bg .close-btn {
cursor: pointer;
position: relative;
display: inline-block;
padding: 0 12px 0 12px;
color: rgb(54, 54, 54);
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 rgb(162, 162, 162);
background-color: rgb(212, 212, 212);
background-image: -webkit-gradient( linear, left top, left bottom, from(rgb(245, 245, 245)), color-stop(0.5, rgb(210, 210, 210)), color-stop(0.5, rgb(190, 190, 190)), to(rgb(210, 210, 210)) );
background-image: -moz-linear-gradient( to bottom, rgb(245, 245, 245), rgb(210, 210, 210) 50%, rgb(190, 190, 190) 50%, rgb(210, 210, 210) );
background-image: -webkit-linear-gradient( to bottom, rgb(245, 245, 245), rgb(210, 210, 210) 50%, rgb(190, 190, 190) 50%, rgb(210, 210, 210) );
background-image: linear-gradient( to bottom, rgb(245, 245, 245), rgb(210, 210, 210) 50%, rgb(190, 190, 190) 50%, rgb(210, 210, 210) );
-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-wrapper .share-popup-overlay-bg .close-btn:hover {
outline: none;
border-color: rgb(67, 90, 160);
background-color: rgb(56, 101, 249);
background-image: -webkit-gradient( linear, left top, left bottom, from(rgb(118, 145, 251)), color-stop(0.5, rgb(80, 117, 251)), color-stop(0.5, rgb(56, 101, 249)), to(rgb(54, 101, 250)) );
background-image: -moz-linear-gradient( to bottom, rgb(118, 145, 251), rgb(80, 117, 251) 50%, rgb(56, 101, 249) 50%, rgb(54, 101, 250) );
background-image: -webkit-linear-gradient( to bottom, rgb(118, 145, 251), rgb(80, 117, 251) 50%, rgb(56, 101, 249) 50%, rgb(54, 101, 250) );
background-image: linear-gradient( to bottom, rgb(118, 145, 251), rgb(80, 117, 251) 50%, rgb(56, 101, 249) 50%, rgb(54, 101, 250) );
color: rgb(255, 255, 255);
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.42);
}
.annotator-wrapper .share-popup-overlay-bg .close-btn:active {
border-color: rgb(112, 12, 73);
background-color: rgb(209, 46, 142);
background-image: -webkit-gradient( linear, left top, left bottom, from(rgb(252, 124, 202)), color-stop(0.5, rgb(232, 93, 178)), color-stop(0.5, rgb(209, 46, 142)), to(rgb(255, 0, 156)) );
background-image: -moz-linear-gradient( to bottom, rgb(252, 124, 202), rgb(232, 93, 178) 50%, rgb(209, 46, 142) 50%, rgb(255, 0, 156) );
background-image: -webkit-linear-gradient( to bottom, rgb(252, 124, 202), rgb(232, 93, 178) 50%, rgb(209, 46, 142) 50%, rgb(255, 0, 156) );
background-image: linear-gradient( to bottom, rgb(252, 124, 202), rgb(232, 93, 178) 50%, rgb(209, 46, 142) 50%, rgb(255, 0, 156) );
}
/* Viewer */
.annotator-viewer .share-viewer-annotator div.share-text-annotator,
.annotator-viewer .share-viewer-annotator div.share-button,
.annotator-wrapper .annotator-viewer div.share-button,
.annotator-wrapper .annotator-viewer div.share-text-annotator {
border-top: 0;
padding: 0;
background-size: 2em;
margin-top: -0.2em;
top: -0.5em;
font-style: normal;
}
/* Buttons */
.share-container-annotator .share-facebook-annotator, .annotator-wrapper .share-facebook-annotator {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wDDBEyHq7FE8kAAAo8SURBVFjDtZhZjF1XlYa/tfY559atcs0uDxnsJN0iGAGJcIgYgkAgoEULCYH6oZtIIPGAExwgQYQExAsSCgmJEcIMfkCAQOEhQjSIILUYlAi6W93CYkg6jSUnHmJXYlelXNOtutPei4e9z1DBDlO40tW955x99vn3Wv//r7WPkD53f+0o9xzYH/8fedypyKggowgIgvHifgSwOGuwENaD+e49B66zu488xj0ffMWWcdz5pf/mvtteC8BdR373MhX3rpHC3ZQ7udo5yf5eAIMZPthGf+D/rzcMPw8h/ODeA69cuOurv+Vzt1wXx93+ue/yhbv+NYL76u/emzn36dmp4trpbQVFLiBCCAH+DgBFFDNjs+dZWOkPVzv9R4P3H7r31uuPfeLwUe49uB95oGd8rCXc+aWj79A8/8ZVO7ft2D6V2/qm5/yFHqsbA7FgLzpAA/JcmR4vbG6yIHfCyXObsrjcfUwGm2++9yOvWfz4oZ/GFH/0/kdnstb4t6/YOfZPV8y19dxS154+vyFDj6nEMS8C4S768cHYNpLZ1ZeNMVJk/P70il/t9O479OEbPgWgN+YQjFe2W7p/x1Qhz6307NSzHekPvIFJMOOv/foQ6PY9FowiE8bHcmYnc7ZPFWyfLJgez2nlYiudvjw1v44PQ9k103ICb7zt849cDpC96pMPagjh2onRbML7wNnFDbr9IU5VvP/ruRfMGA49r943y7V7J5gebzFSOPJM0FJ0Ag//51k5euyCBTN55rmu7Z4dkTyTKzc7g13A2UxCEMJwKs+02Oh5ubDSwzk1M5O/DVzg5rdfzQ37ZnAqiMQ8i2jKd5y+VSgD7yV3sLzWY26ysCLTzPobbYBsfem0TLa3q1mgNxjS63taRRD7G3ThA7z1hl3c+LJZREjgatWWx2BYMMLQE3Jhc3NAbxAEC+KHPd0GZGYiIQSCD4hA/K8vqL7ns1+im8frBrMTBfv3bUd1axK2gqvv9z5gPuAVsRAihhCvZmCEEEktwQgh8OdRr5RmSpeUcjcunxtl+1TrjxeXAJ4536GzOcQwLqz2EIyhDzgnBAsJT2AkRtASYkPF8MHzgr4sWsUyRqMOnQEqMDfVot1yiEgFysxQVR766Ql+9qtnyDPFMPwwUOSSMAgWDLOAmbEdyLwPeO8JPpqeDY2gniYHKyBCI2qNSEpVG0CN0ZGswbsa5PJ6nx/98gxFIYR+jIKFkKpV5KMFY+g9fui5HMhWlldZC+eZnRpnbNsoG70N1LVRFUQUESqwZkSDkKYQDTOwABDAdMvimrw7dmoFVRgMDQUChlOQZEkbfkCns8H5c4s8++wCP3kdZL1Bn/7yKheWlul0Njh54hmmJsZotVqMtEdotQpcluGcQ1URpxFZQmHA3p1jvHTvBN4MFWHv7rEt4MrfXdMjvO01l4EJpVb+6zdn+P/j5xgOBmQa2DEWWFpaYW2tAx+DTBBEY5rMB3rdPquAsAGiqDryPKNoFWR5Rp7n5LnDuQznFFXlql07+Je3XMXABzBwKpiFip8lyCt2jvGeHVdBzCqZUx574jRnzi4xPprTHskAcBrnZwmymC4BU0ARNJmpYCgGdHtDur1hg3OOzCmSDHj5pVOICEXmqpSXoMpIAjinuIuJTjTRSUCVZJ7QTRGkvFh+y3OJ+CUfq7yIYAgW4nFodDt/ucELgtbAkBQowEFWehgioIJo5FqwCFAaN5XVoFy5SAx+u108T/F11JoGf7Ha2W7lyerrIMRnKHQgqyYVSRFTDEVTlKBxk5EWU6pbUBF+8etnWVrtRy9V4Q37d3PT9bu3CEWAx598ju//7ASSyoQI/ObYAtvGisa8jYBIKRJqcCKS+JNsRiMfRQScqx5mCCqKKZw4u86Tp9dABOeE3XNjFcBmaZs/3+GHj5xExJJDGU6Moijw3leUEo38ZrlMMVobbQlUEzek5oikZcd0xWtqIE5xaakqgtOL13IVpciz1O6Xvhkrh2zhfbVdoh4tpd1ERVm6IVaHqG6TSjaNylFHlMqyLtGpSVNsITlHMn61inv1/JCRUlqSXysepOipVkClSeaqNRC0VJ3QeMAlFCsOJN4Vq3dATOO5FAjKRUgCWK64jE8ZalOtlZV8UbRpNw6HEBLX5E9GkGouEat3xpJAIpRGKQgYZFjTRrRSk9HkYDynjWMrF1G1WUq5yecS+6w6+pF/sclO9hV7oYo2iMACZIglbtQWUltODa4Cj2C4LaKqxxL5eokIxvMuRY8oDgGjTHHTYhQ2GzZTWklZcswaXGyAE3H1SqUGFR8oldIv3o4nCkDiXQ2y9ECpcJA4aLXC6vZOEgapFB1vcvG4nAgXsZc0cUlUppdUMaKIhZgU0/icZDOGmsSqkVyk8sFSkalJENmixgocDXCNWo026SCXDGAdAa04aCmSiCEiYpWrCPSTikOyiyyrH2xNw0wcrG6m4YvS4GhZq19AxXH+VJnNJ6HEBTrVmPVy07wGqhIwbwwGgZFWxthojg+YNNRbprxMawmuqjpVN6Rb9ykX9cG4mOi3rkq9DzA+VtBqZXT7ARWB14POTDqfu+HS8lqv125ldvncNgvBokuJWPlAMWl0Q7GkqUZfFIl1WZ0DyV5AxSW/pXI3UTUzoVU4u2xulOHQ6Gz0enk27MpdoK+ffjiM5SvHl1bWl9Y6A/5xzwRz022zgIGIGVaZeZN3qeuJxy42t0n565vG4nKf+cUe8ws95he6XFgbsLLua6NGMRMLJiIqtmf3NnbNtu3JM6tmvvfUbHZuvipOt95yYNfxjeu+7Mb2vPtV+2aDaibHTq/J4oWu9Qci0afURFRiqWpWmLLjcZRlc/tkwexklhpZwwg4heXVHmfPbxoEEQIigXauduXOEdm7u23zi5s8cXzBT8nxu985df8XP3D/mUEG8Kapb5/ztI6c2Che/j+Pu5fsu2Y8XP+SaetsBlntDGzgY5VGIneaZi44RGt1lwKxaq8cwBwWAjOTBTOTuZgFEwKtXGR6PEPFwvGnO3JqfkVm9MQPrmn970MfuP/MAMB9/Lb3cvsDR3nnayeeHm11n+l0s6tPPZftWFwe6MCbFFlmzjlxTsmcok5QdWSqqNO4cXKKU0WzyEOXuXisghNJv6DOyITEX2zQ98wvdjl2asWWlpY6O90T/76n+NVnHzj84DGAz9xyfUzxHQffz6HD3+TTB2/KO/zDqxcGe/75wmDnDV7a0yIuvv55XvNqUvYwjY5bU7skZRtgkN4UYLH3CxgSQowsZhaGwxYrZ2eypx+dcScfvu/wQ08B3HnwPdx3+Hu1H9x+8Ga+cPg7HLntSk5y42QvtHcGdMIHXKphYFX/0XzZljyNurczq984WP32oX4Zb2CCqpgKvUyHSy1WFj57+MebAHfc+m8c+sqDjbY1fe740Ps49OVvAXDngTfj3ax4b5hPXGpugSykM89/v9sc98clTxtl1amSuYFN9/6DT359AMCtH7yZrxz5TjX+DwV2mkY3fbDAAAAAAElFTkSuQmCC');
}
.share-container-annotator .share-twitter-annotator, .annotator-wrapper .share-twitter-annotator {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wDDBEyN+x3i6UAAAriSURBVFjDnZhrjF3XVcd/a53HvXfuzNieiY2d2q6dh0NJQkPACTVEhArlQwlIcflQoxZoSEIDLaqqCpCKQAgJhNRviEQkadqUNK4ixVTCFREWqRSJtrHSpqQJips0cZz4lbHH877nnsdefNj7nHvueJJSjrU955577t5r/9f6/9daW2hd9x+f48FbtvLp4/ORs6pvqrG1vpcwxp4oEF4SBRxY/VL7x2bNT+pbE8HK0kWq2QO3XJEB/PG3T/PAgfeNrcmf/OfblNMp/7x/G/cfnztQVfZbvUgOdmLdHYmIKIj5t6W1riAYIONWt63CEMT83bqvqEDKqlocVDxbVO6pK4bzX/+72z9g9z3zGg99+JqRgfc89w6P3LqNTz13/q+qyv50Vz+enUkjJiJFFUrzM8roJyCGrMMTWw/x6IHV9+afKhAJ5AYruePsoGShqI499KHtdwB87PN/zde/+DfIvd8+y8MHdnDfd85/tqjcP9w0k6ab0tgGpZOTqyXLhfMIyWjtMUPrZxugaHY5ovX/Fuzdlkbs7scmInJiKedCVr3w8IHtN4+5+J7/OrOzNI7um0o+uL2fMJeVvLZUoCIeKQEx706D8NwvIoBKCyHv1MsQa/bjRq4HwxmkCj87ndp0qvLduUGeZ8PPP3L7nn8kIE1ZVbf2Yvngtl7M0rDixGIOYRFnYCYMHcQq7JtK2D/b4Veu6PLzW1K2diMGlcOZYOFd1/rrxBrEzMzPGWLXBVMzZ5xYziUrjX1TaZojv/0HPWKA+JMPPaV5nl+7c6pDJNgry7kQEDHzrssqx1WTCXftmuK66YQ00sZp72Qlz74z4Ni5tYZIbfdYiN8WsyAYai2qLecV5waF7ZhIZEJtV/bot67m0K+fUHp9dVU5m6qwUlayWlTBnYYJOHPs6EXcfc0mbtzSIYlqHvvpt3Zifmf3JB+a7SLqN1SPmlpmXnpqjzhcg7ZHFFSF04NSRKCr1ndlPgUQqznMuSgSWCl9UDmxJsojlFtme+ycSABjvjB+nEOOMBM5rutAZMLH907xvfmM3NaTw28U87HpzBDUB5A4zI24vlpYTUaxIo8A1DknzlyIBz+5M4cz7+JI4de29bxxpXGqgL0pXN8xuiK8OPCzx6rcuLmDM2shbEGOWuwNsV2FEKpf98haszkXNCy2oOgEMfVGSpAWowJmujEAZwtjOhYuOT+RCsQCSxVMR/D+fsx/nHPEul5ehEQ8W4XgIQvRJy5IjoQMZH6TwdDYTDAzXCC+w9CW4rmWu0yENWeB4aPYd+H7/TNddkwk6+Wb0hknVwuOnl6hMIgDCK5B1k9kwWvWylZxZY7KjQuoqbUUf7RcYVCZjCUt17qf6cYN2usF+hdmuty1a4rH31jk6bOrJOLJgkmTo7w3vcFV8HV8frDGwuoq7x/m9OOI3DniKEICDU3G00E+0uNGNQbOiFq7Xp/xBJhQQ4GP791EqsK/nV5B1acoNaNwjtWyYi0vOb+WcWEtqxE0Lg1z5gYZy5Hy5tKAXhLTiyL6acxkHI+t5MZykL9OFpBgdAQSpTG2cH5DOdAR+LmOkIpxx/YJvn9pwKvLOVlZMigqhlXFUl5yYXPEwrAgc36lWEyIRYlEMbwol5SsFhWX8pxERxGfVTA0iMxQkVB+CU4gx8hNkGokM67JFrDijOcGjtv6EZs7MQkVp5bXAoNdcCtEIkQiTWjFiCAiQWSVSKVZfExxgcwZq27cx7ZBMbAByAjCRTMqZ0Qq7JxIiVUonQuqGJZDUJVm2VjFy4WG4klEUAl/xyji2ViYIBj/n6tyRiSjzQKoeO1x5lC1xkgRDS4ORnnAfPJV8YapEgJ5xOLc2WUy4jYsrcavzBm/3NcmF7+1WgCKqmHOUFGUkPxb4h4r6tFSQUMpNdqFjBWlpUGxgYGzMXT13Y2MRLi2I2xPfdS+tJjx0tIQVa/BiPeKiPeZiiIBmNjEPILBMK1jMoyoRZLCGaVbvzjcPKFsT/Un+9iM+WHJg6/Ns1A4UhWcRZi5pnJqRk0SqRGzkKWDkRoQbMNVGuTmxlB1VrcE7345M06tFbyxWvDV1xd4eWlIP45wzoViV3BApJ6AtU1jMTiyXAOL/T9tsbh0RuHGHRy/h0DXqJlBLMLz8wNeXMrZnES+plYF57xYB2LW0lVPpBKKH9FgkNbxF9i9HkFnFO1hYx3l5ZdIkJWEz+6b5ckDVwaxD0ZpWLMGRf2oAyb2VYtvDZsXtUZ0PK42ikEnxuncheJ2YxenYszESlfh6n7K396wlb98aY44xJRhKDbWnDUx6Br3hhhsejZ/FwemiQjTEZzJL2fxN+crSqveRR+FyoyZWPjYtoQ9HeEXt3S5aXOXHy4OUfM9ChKkxuqVPTiqoQtrS8uIyRCp8upyDsBNk8piaRQ2PhQjFSMRNhhGV2G5Mr5yNgeBXqzs7SdE7SyGjBBsJTCtMwfrvqyNLBw8e2EAwL6JmNlIGFa+EPhphplwsTDWqlCadWLi9Zpbx6GMzlO0tqgmS20Ywe0OeGFhyGJeYmZ8ZmdC5YyhM/KfYmTON5sTkTdwqXSYemNUW17DELFGPXQUbyNq1/Ii+MrixErBN88NEIHJCD63O+XqrhIjLJewWMBi+R6j8Gc7n/iZFBBKZ5xaK70466iyaAjbljEN/YcDEh0VDNKSgQQ4/PYKvUi4632TXNkx7r0y5VTmmC+Nwvnfv9sZkgA7OsJVvQjM+MHikFeWCyL1LYWI70uTEITGKAhjw5kKljvH7iSlNEhrMMXrUV1MPHZqlf9ZKfnCdZtIFa6p/fV/qm78HO8MK/7+R4tUNTHNUJQKx2wnxuEonBGZFy297QsHq24+eHuh8C3MVZMdnMkIahkxG4XjC0PuOn6Bx95a5fSgZKl0rJT2E8elvOLxt1Y49L0LPq2FJFCztwSunUopHFzK8tVN508uA8R/Nof95mDpRxdWs8HaVKf3gU2pLZWZrDlfhdDKvBLqNxXhqbMZXzudMREJm1INuTtUnWatHtsonXExr0gFtiSRb4iCW0V8Jb23n9hsGslLCxnJYOXkDV/+8zMNSfYc+8pzyWD5+RcWMgRk/0yXK7tx6OJ8b1yFhO7MmnjdnCidSMkcZAaZU4ZOyCyMCjLn68ipWElUqEK8VyEzIcK1/cRumE7lTFbaW4PC7fz+00eGbxRLY+nzU39032+8dvBzR+Jef+rmzR2b7cRSOONi6XNu7WaVdWKudYER+B8krOlxzXzfXZ/JON97Y0Yvgi2hy391eWivD0V2HHvsXyZf/s5f/NOT/3oGIPrdT/weP3zxv5m9fv+bNzz/jVcW9ty4/6RMbJofllIikkZ+54lqa8jYSFVJREgiz8REhUh8oo/D6UOkECNEXjqIEIaVcS4r7eWFzF1cXsl2Pf2lJ3pnX//iA48f/vEYte6+514efeRhbv39+/VXL5z4pYv77/joyp7rby07k7NeEmUcwaZEq8skHetlauRcOHypw8JcOB80C/eg5TDrzp1+Y8sPnjlW5sOnH3ziyTcB7rzzTo4ePTpy8SfvvpsvP/ooAJ/5yO2TMbZVRKYtiuNaRUZnN/Vp1egc0TY4l5bW0bA/h5HWM0Ewc47c0uTSan9m7kuPP5EDHDx4kCNHjlxewh06dIjDhw83n2/7w0+zTaoxpWuIKkJ9jC7vVU237tS1PpvRm5zkmRdf5uy3/r15a3p6mqWlpebz/wJ5Ut7CxANClQAAAABJRU5ErkJggg==');
}
.share-container-annotator .share-google-annotator, .annotator-wrapper .share-google-annotator {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3AsJEzYNSj34jgAACUBJREFUWMO9mF1sHNUVx3/3zuxs1t7EEEOcDxJBGycCFBMaRzFSw1v5KN9BSA1QaEQfEBVtpJYWUKMQwUMlmhdo+oZQRVNCQoooaqAEAX0oUqkKIQ2IKNAmNiixieP4c2d3557Th70zmV2veaAVK408M75z7v98/c8519D8M/7S3PPX+RPAzO8smMnpurQCCIAQkJduumXDgsAurjvXtGakcxkHVt5JoElb6UYNrjjG5CX7MRLOiWKJUTZHddIVCtgAjaKCvHLwk0OP7/rbCY+nHubART+8+BvLf7ay9/fRxMR6bYBr+oUsZbq4loLU2u+slvq8zznVM4F1xTkBnh841nTOEM0WwKV3d3Pv9dfvvHrLW786+UU8GXoTFRSiB3p6ngrPjK53om2dW48qTMVKwUl7CwJV6pyeGsXKvDkBjgUJLphG2gaQcmFn+NPf/HzVB5seOvynEDAKEbB0QWXmWjdTAYO2i78kmmE6ViKnc1hQqZJwpnL2SwFOhAlSmkSNtkdoMJcuL94FvB56IPN6S6UlOjmJVmMwpq1uUqpQrSk6F0CUSiBMVCexLpkT4HSUQH1irhQ0GEXrHQuBcgqwEIuUqgbEWjAGVW/IHNbEKKGpEprqHFtbCqZO0RWwUpgTYOgsNSlhTM5RqlmcGAOTcSEASlmSnBQJ7iiXCcOQwFqstdggaNwbg7GWwEzS9f4tGGPntGAHlqv/vmJOcKqKAHdqD6KKikNEERXEOUSVJHFUKtMGCFMLGgO2ZC1REGCDAGstQRBgjWmAtRZjDNYW/2eyU1VC1QZYMagqTgQRiziHc6DOmoZP2nysIuAFZFqLNP6Xe/9VwbXeq2pjv/weWdC0ZKHmyJM2YFQVY8xXApl+mxmijcI6i3ubIigHKtXqS0ACiAgi7XkxCIImQMYYkiRpIolUtuT2ze8XzrJg7hJfYtpZM43RxUuWsLinhyBsFlWr1Tj0/vsZ+BRcX18fw8PDnDp1KnOlthgjM1ATwPyC3EcigjWN3FegVq2yatUqbtm0iVq1SpIkXLF2LatXrwbgnXfe4bPBQV599VVEpMmC09PTPPTww7y4bx8v7t2LtbbtvuotOhtgXhvvPhsEmXtcknDZ5Zfz6507eeaZZ3jl5ZcBcM6x44kn2LhxI6tXr2bH9u2g2gCQizdUqVQq1Gu1rHVpikWRBgafpLOSJM1UybtZBPVxVowifrx1KzYI+Ovbb2OMwRhDFEU8tm0blUqF7u5ufrJ1K7VaDRHBJQmJv+pJ0njnHPV6ncRfGUPkMGirBaXVzSJozgVGlcVLl7J8+XJEhLhSabjQWkSEIAx54+BBvnvDDazp68ticv3AAL29vagq1Timq6uLDQMDdJ13HgYICwX27d3LmdHRhlu9gWbHoKeOFJwYAz7+0lgqFAqUOjqIKxUuXLSIocFB8G4xxnDs2LEmzhQRuru7Wdnbi4iQJAmFQoFFPT04L7NYnEchDHHerXkvNgE0PjBFBIzBeAuKcxAEGBFmpqeZnJigWCyy9sorOX78eKMM+gSqxlXCMOTw4cPElQqlUon9+/bx/O7dAIyPj/PKgQPsef559vkkEecodXRk3Cot1GbzSZJaI13o0njwMTg4NMTRo0dRhRtuvJEgCDKNa7Uaa/rWMDg4xM4nnySKoixuy+UyneUy88tlAIpRxHz/XC6XMcY06nCbamVbB4I0KdKy4zw4EaFeq/HLRx9laGiQZcuW8dTTT3PxJZewsLubLffdx8qVvfzgnu83lUeXynAOp9oYeBScyDnZzmVGSb2orUStuRgUb03rY1OMAU81E+PjbLn3Xr61rp8VK5bznWuu4fY77kCc467Nm6lVqxm9pNUppZhCGPLcc8/xybFj56pQzq0iAh60eoKfTTOpVjkXZ1p6zUSEf/7jXf64fz9HjhxBnBDHVTo6O86FR/qdl+lECAsFDr7+Ov/+9NMsIbKk8PLTPWltFkzOeprrLFL3ZIA9t1WrVapxzOEPPuDs2Big7NjxOH19fcSVCurcOdemijs3S5a0yk9jvjWLUwaXtDQZg/X0ob7UGWOYiWN6enq49rrruGLtWlYsX4ECURRx/sKFbHtsB7979lleeGEPxWKxqa5KS5VKAWquWcgbaZaLNdedaIsLnHOU5s3jF488wt4X93PRRRfx2127uO22W7lqw3o2b97M6dNfEASWu++5h741fTifmc5Xj6b71MJetnoXp9mcKhV4kAustUu6Fiz4HsZks4zJdTIiwpM7d7Lx2xt54P77eWHPHmZmZigVi3R2djI2NsYbBw/S37+eRYsuZGzsLIfee6+5Cc1VilZKaW2KnXOnJiYnX7atRN1KMapKtVrlpptvZt26fl77y2t8+OERSqUShgZdJM5hjGF0dJQdj20nDAt0dXU1U4m/T3LWzHspX0GkXQySxqCnCONcVmdr9Tpr+vqI45gkSXDONapAztqpkh9//DGqyokTx3FJ0tShz9X3Scu7tlmsuRjUFm4yxvCvw4ep1Wps2DDABd0XEMexH3BcZoFKHDMwcBUjIyO89eabmfXSmJPc2jz9tLo39WT7maSl2IsIYRjyh927+eijj6jX6zy1axfr+vspFAqEYYi1lqhQ4NLLLuNHDz7I9m3bOHHiRLMCaZLkQLpcAmaVJ0fSqVdCYFkQBFcu6el5SVUx6YjpKSftijs6Orh10+30r+vnm70rOTs2xsjICFNTU0xNTjE+fpYDB/7M558NEUXFpjmn7RSXb2bzVNNQ4NDJ4eEtswCKL2nGx1d270th2nYZYymV5iG+UQBwviFtd3Ki7UDmO+r8mNEAeejk8PCWsN0BEKqotdkJkslNcelAZIyhVqs2Wbjd7Puls3BuBsmefbvXOtWpc66ayTD+cCaXQKblyNVo7tzGrzW+uWidsZuUz2d0m7+5mTsBNPTrHTAuqiPAItPcQWSdjvElsOnYtY07TZsBPA+u9d7kvJACrdfrhwAN0uM3YL6InC1G0Xpoc/jZEgKznluG/Vnv53D/LOWMwYkcHT1z5llV/Tw9NJ8PLAZ6wyDoK5fLA9baC77mQ3Q1IHG1eqwSx++KyIfAf1IARWCBB7kM6AbKQOFrOu1P60QVGAdGgM+A0yZXUQpApwfW6UEHc4XU//ln/MSRADEwBUwC8X8BTYvqIryh+pIAAAAASUVORK5CYII=');
}
.share-container-annotator .share-email-annotator, .annotator-wrapper .share-email-annotator {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAABIUExURf///7KysrKyss/Pz9DQ0NHR0dLS0u7u7vDw8PHx8fLy8vPz8/T09PX19fb29vf39/j4+Pn5+fr6+vv7+/z8/P39/f7+/v///37mbPQAAAACdFJOUwCWb//7SQAAAQNJREFUSMft1M2SgyAQRtHkC0RtbP6V93/TWZikFDuQ2c7krrCKU1gKXC7f/lNX9LvuAVB6AUdw78y/V2CEXltpjEcwmabQMNMR0GwbQsPOVAF2AXqR0wiOK2DYh/RGaKTg2VTA+pgXUWgsOXorghUq1ymsDVBOQqE0QYFK+xRKBxyFQumCvVAoH4ACFbe2+f0VnkKhfLICnmsoPJ46X2l7q1u4PUYdgNdxeY2aQDp4b/40+5AyxM2NLGw+YhcisrhbM+J5e9NsPWLKUinCnw7QZBg+hCgVggfXR3QksHVezlkGVZfAADIzs5Ving1hqO6lYZyIjBzRNA7He+nXV+W3v98P7gg+L5LCf08AAAAASUVORK5CYII=');
}
.share-container-annotator .share-button-annotator, .annotator-wrapper.share-button-annotator {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC8AAAAvCAMAAABE+WOeAAAAA3NCSVQICAjb4U/gAAAATlBMVEXMzMzZ2dn////r6+vPz8/n5+f5+fnl5eXT09P19fXz8/Pg4ODX19f7+/vR0dHp6enu7u7d3d339/fj4+PV1dX////b29vt7e3h4eHx8fHJkyUPAAAAGnRSTlP//wD//////////////////////////////zDtagYAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAAedEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzUuMasfSOsAAAAVdEVYdENyZWF0aW9uIFRpbWUAOC8xNi8xM7KZeroAAAFnSURBVEiJrZaNbsMgDIS9jpCQ0dBoVaW9/4vOQHD4OVIh9aRKLf0UG9scoduYqF7Qs1UUpeys3/Buo1Kbu+BnQpo7/KogznmtiMcPr0MIv1/gRHvNLy0zcXH0dPxYSh483cR/TBmBerlPKYMUYT75FWQsndJpZRUeFTIr4SGVeFjJlg8ZUb5wnU94Bn8cwr/u9X5ZLvD1iHn9SjYmW908r1t6+eM0bNGvlCSB3e4MfqOovGO62XqRO6U702SZl+LH+E9uiwHTFKSYT9+NbNH1DgJXVHiZl/urS+c86s8VD/r/UX40H9mvgZ06+VQ8qWfXV2L9pb+xX767TcuTLJifn/44hPlp9mdNMfS5NJz/p/HzCcZ5652vBzwux/kCDVKnYeYRLvxBjm+2veQPyH/AeIj/IH8D/OlvIKN2nDL/BP7c2G3hz8D/Kzuv/B9FyPvV3C/D99fw/dgN0bt/vcbud6+x94e3+gd13Qxqz2VnfwAAAABJRU5ErkJggg==');
}
/* Api */
.annotator-wrapper .annotator-hl.api {
background:rgba(0, 190, 99, 0.3);
}

View File

@@ -1,97 +0,0 @@
/* Editor */
li.token-input-token {
overflow: hidden;
height: auto !important;
margin: 3px;
padding: 1px 3px;
background-color: #eff2f7;
color: #000;
cursor: default;
border: 1px solid #ccd5e4;
font-size: 11px;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
display: inline;
white-space: nowrap;
}
li.token-input-token p {
display: inline;
padding: 0;
margin: 0;
}
li.token-input-token span {
color: #a6b3cf;
margin-left: 5px;
font-weight: bold;
cursor: pointer;
}
li.token-input-selected-token {
background-color: #5670a6;
border: 1px solid #3b5998;
color: #fff;
}
li.token-input-input-token {
margin: 0;
padding: 0;
list-style-type: none;
}
div.token-input-dropdown {
position: absolute;
width: 400px;
background-color: #fff;
overflow: hidden;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
cursor: default;
font-size: 11px;
font-family: Verdana;
z-index: 1000000000;
}
div.token-input-dropdown p {
margin: 0;
padding: 5px;
font-weight: bold;
color: #777;
}
div.token-input-dropdown ul {
margin: 0;
padding: 0;
}
div.token-input-dropdown ul li {
background-color: #fff;
padding: 3px;
margin: 0;
list-style-type: none;
}
div.token-input-dropdown ul li.token-input-dropdown-item {
background-color: #fff;
}
div.token-input-dropdown ul li.token-input-dropdown-item2 {
background-color: #fff;
}
div.token-input-dropdown ul li em {
font-weight: bold;
font-style: normal;
}
div.token-input-dropdown ul li.token-input-selected-dropdown-item {
background-color: #3b5998;
color: #fff;
}
.token-input-list{
padding:0px;
}

View File

@@ -1,65 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>
This is a custom SVG font generated by IcoMoon.
<iconset grid="16"></iconset>
</metadata>
<defs>
<font id="VideoJS" horiz-adv-x="512" >
<font-face units-per-em="512" ascent="480" descent="-32" />
<missing-glyph horiz-adv-x="512" />
<glyph class="hidden" unicode="&#xf000;" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" />
<glyph unicode="&#xe002;" d="M 64,416L 224,416L 224,32L 64,32zM 288,416L 448,416L 448,32L 288,32z" data-tags="pause, media control, audio" />
<glyph unicode="&#xe003;" d="M 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" data-tags="volume-mute, speaker, media control, audio, mute" />
<glyph unicode="&#xe004;" d="M 274.51,109.49c-6.143,0-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0,33.941
c 40.55,40.55, 40.55,106.529,0,147.078c-9.373,9.373-9.373,24.569,0,33.941c 9.373,9.372, 24.568,9.372, 33.941,0
c 59.265-59.265, 59.265-155.696,0-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" data-tags="volume-low, speaker, media control, audio" />
<glyph unicode="&#xe005;" d="M 359.765,64.235c-6.143,0-12.284,2.343-16.971,7.029c-9.372,9.372-9.372,24.568,0,33.941
c 65.503,65.503, 65.503,172.085,0,237.588c-9.372,9.373-9.372,24.569,0,33.941c 9.372,9.371, 24.569,9.372, 33.941,0
C 417.532,335.938, 440,281.696, 440,224c0-57.695-22.468-111.938-63.265-152.735C 372.049,66.578, 365.907,64.235, 359.765,64.235zM 274.51,109.49c-6.143,0-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0,33.941
c 40.55,40.55, 40.55,106.529,0,147.078c-9.373,9.373-9.373,24.569,0,33.941c 9.373,9.372, 24.568,9.372, 33.941,0
c 59.265-59.265, 59.265-155.696,0-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" data-tags="volume-medium, speaker, media control, audio" />
<glyph unicode="&#xe006;" d="M 445.020,18.98c-6.143,0-12.284,2.343-16.971,7.029c-9.372,9.373-9.372,24.568,0,33.941
C 471.868,103.771, 496.001,162.030, 496.001,224c0,61.969-24.133,120.229-67.952,164.049c-9.372,9.373-9.372,24.569,0,33.941
c 9.372,9.372, 24.569,9.372, 33.941,0c 52.885-52.886, 82.011-123.2, 82.011-197.99c0-74.791-29.126-145.104-82.011-197.99
C 457.304,21.323, 451.162,18.98, 445.020,18.98zM 359.765,64.235c-6.143,0-12.284,2.343-16.971,7.029c-9.372,9.372-9.372,24.568,0,33.941
c 65.503,65.503, 65.503,172.085,0,237.588c-9.372,9.373-9.372,24.569,0,33.941c 9.372,9.371, 24.569,9.372, 33.941,0
C 417.532,335.938, 440,281.696, 440,224c0-57.695-22.468-111.938-63.265-152.735C 372.049,66.578, 365.907,64.235, 359.765,64.235zM 274.51,109.49c-6.143,0-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0,33.941
c 40.55,40.55, 40.55,106.529,0,147.078c-9.373,9.373-9.373,24.569,0,33.941c 9.373,9.372, 24.568,9.372, 33.941,0
c 59.265-59.265, 59.265-155.696,0-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" horiz-adv-x="544" data-tags="volume-high, speaker, media control, audio" />
<glyph unicode="&#xe007;" d="M 256,480L 96,224L 256-32L 416,224 z" data-tags="diamonds, bet, game, gamble, cards" />
<glyph unicode="&#xe008;" d="M 0,480 L 687.158,480 L 687.158-35.207 L 0-35.207 L 0,480 z M 622.731,224.638 C 621.878,314.664 618.46,353.922 597.131,381.656 C 593.291,387.629 586.038,391.042 580.065,395.304 C 559.158,410.669 460.593,416.211 346.247,416.211 C 231.896,416.211 128.642,410.669 108.162,395.304 C 101.762,391.042 94.504,387.629 90.242,381.656 C 69.331,353.922 66.349,314.664 65.069,224.638 C 66.349,134.607 69.331,95.353 90.242,67.62 C 94.504,61.22 101.762,58.233 108.162,53.967 C 128.642,38.18 231.896,33.060 346.247,32.207 C 460.593,33.060 559.158,38.18 580.065,53.967 C 586.038,58.233 593.291,61.22 597.131,67.62 C 618.46,95.353 621.878,134.607 622.731,224.638 z M 331.179,247.952 C 325.389,318.401 287.924,359.905 220.901,359.905 C 159.672,359.905 111.54,304.689 111.54,215.965 C 111.54,126.859 155.405,71.267 227.907,71.267 C 285.79,71.267 326.306,113.916 332.701,184.742 L 263.55,184.742 C 260.81,158.468 249.843,138.285 226.69,138.285 C 190.136,138.285 183.435,174.462 183.435,212.92 C 183.435,265.854 198.665,292.886 223.951,292.886 C 246.492,292.886 260.81,276.511 262.939,247.952 L 331.179,247.952 z M 570.013,247.952 C 564.228,318.401 526.758,359.905 459.74,359.905 C 398.507,359.905 350.379,304.689 350.379,215.965 C 350.379,126.859 394.244,71.267 466.746,71.267 C 524.625,71.267 565.14,113.916 571.536,184.742 L 502.384,184.742 C 499.649,158.468 488.682,138.285 465.529,138.285 C 428.971,138.285 422.27,174.462 422.27,212.92 C 422.27,265.854 437.504,292.886 462.785,292.886 C 485.327,292.886 499.649,276.511 501.778,247.952 L 570.013,247.952 z " horiz-adv-x="687.158" data-tags="Closed_captioning_symbol" />
<glyph unicode="&#xe009;" d="M 64,416L 448,416L 448,32L 64,32z" data-tags="stop, media control, audio, square" />
<glyph unicode="&#xe00a;" d="M 192,416A64,64 12780 1 1 320,416A64,64 12780 1 1 192,416zM 327.765,359.765A64,64 12780 1 1 455.765,359.765A64,64 12780 1 1 327.765,359.765zM 416,224A32,32 12780 1 1 480,224A32,32 12780 1 1 416,224zM 359.765,88.235A32,32 12780 1 1 423.765,88.23500000000001A32,32 12780 1 1 359.765,88.23500000000001zM 224.001,32A32,32 12780 1 1 288.001,32A32,32 12780 1 1 224.001,32zM 88.236,88.235A32,32 12780 1 1 152.236,88.23500000000001A32,32 12780 1 1 88.236,88.23500000000001zM 72.236,359.765A48,48 12780 1 1 168.236,359.765A48,48 12780 1 1 72.236,359.765zM 28,224A36,36 12780 1 1 100,224A36,36 12780 1 1 28,224z" data-tags="spinner, loading, busy, wait, wheel" />
<glyph unicode="&#xe00b;" d="M 224,192 L 224-16 L 144,64 L 48-32 L 0,16 L 96,112 L 16,192 ZM 512,432 L 416,336 L 496,256 L 288,256 L 288,464 L 368,384 L 464,480 Z" data-tags="contract, minimize, shrink, collapse" />
<glyph unicode="&#xe00c;" d="M 256,448 C 397.385,448 512,354.875 512,240 C 512,125.124 397.385,32 256,32 C 242.422,32 229.095,32.867 216.088,34.522 C 161.099-20.467 95.463-30.328 32-31.776 L 32-18.318 C 66.268-1.529 96,29.052 96,64 C 96,68.877 95.621,73.665 94.918,78.348 C 37.020,116.48 0,174.725 0,240 C 0,354.875 114.615,448 256,448 Z" data-tags="bubble, comment, chat, talk" />
<glyph unicode="&#xe00d;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,352
c 70.692,0, 128-57.308, 128-128s-57.308-128-128-128s-128,57.308-128,128S 185.308,352, 256,352z M 408.735,71.265
C 367.938,30.468, 313.695,8, 256,8c-57.696,0-111.938,22.468-152.735,63.265C 62.468,112.062, 40,166.304, 40,224
c0,57.695, 22.468,111.938, 63.265,152.735l 33.941-33.941c0,0,0,0,0,0c-65.503-65.503-65.503-172.085,0-237.588
C 168.937,73.475, 211.125,56, 256,56c 44.874,0, 87.062,17.475, 118.794,49.206c 65.503,65.503, 65.503,172.084,0,237.588l 33.941,33.941
C 449.532,335.938, 472,281.695, 472,224C 472,166.304, 449.532,112.062, 408.735,71.265z" data-tags="spinner, loading, busy, wait, wheel" />
<glyph unicode="&#xe01e;" d="M 512,224c-0.639,33.431-7.892,66.758-21.288,97.231c-13.352,30.5-32.731,58.129-56.521,80.96
c-23.776,22.848-51.972,40.91-82.492,52.826C 321.197,466.979, 288.401,472.693, 256,472c-32.405-0.641-64.666-7.687-94.167-20.678
c-29.524-12.948-56.271-31.735-78.367-54.788c-22.112-23.041-39.58-50.354-51.093-79.899C 20.816,287.104, 15.309,255.375, 16,224
c 0.643-31.38, 7.482-62.574, 20.067-91.103c 12.544-28.55, 30.738-54.414, 53.055-75.774c 22.305-21.377, 48.736-38.252, 77.307-49.36
C 194.988-3.389, 225.652-8.688, 256-8c 30.354,0.645, 60.481,7.277, 88.038,19.457c 27.575,12.141, 52.558,29.74, 73.183,51.322
c 20.641,21.57, 36.922,47.118, 47.627,74.715c 6.517,16.729, 10.94,34.2, 13.271,51.899c 0.623-0.036, 1.249-0.060, 1.881-0.060
c 17.673,0, 32,14.326, 32,32c0,0.898-0.047,1.786-0.119,2.666L 512,223.999 z M 461.153,139.026c-11.736-26.601-28.742-50.7-49.589-70.59
c-20.835-19.905-45.5-35.593-72.122-45.895C 312.828,12.202, 284.297,7.315, 256,8c-28.302,0.649-56.298,6.868-81.91,18.237
c-25.625,11.333-48.842,27.745-67.997,47.856c-19.169,20.099-34.264,43.882-44.161,69.529C 51.997,169.264, 47.318,196.729, 48,224
c 0.651,27.276, 6.664,54.206, 17.627,78.845c 10.929,24.65, 26.749,46.985, 46.123,65.405c 19.365,18.434, 42.265,32.935, 66.937,42.428
C 203.356,420.208, 229.755,424.681, 256,424c 26.25-0.653, 52.114-6.459, 75.781-17.017c 23.676-10.525, 45.128-25.751, 62.812-44.391
c 17.698-18.629, 31.605-40.647, 40.695-64.344C 444.412,274.552, 448.679,249.219, 448,224l 0.119,0 c-0.072-0.88-0.119-1.768-0.119-2.666
c0-16.506, 12.496-30.087, 28.543-31.812C 473.431,172.111, 468.278,155.113, 461.153,139.026z" data-tags="spinner, loading, busy, wait, wheel" />
<glyph unicode="&#xe01f;" d="M 256,480 C 116.626,480 3.271,368.619 0.076,230.013 C 3.036,350.945 94.992,448 208,448 C 322.875,448 416,347.712 416,224 C 416,197.49 437.49,176 464,176 C 490.51,176 512,197.49 512,224 C 512,365.385 397.385,480 256,480 ZM 256-32 C 395.374-32 508.729,79.381 511.924,217.987 C 508.964,97.055 417.008,0 304,0 C 189.125,0 96,100.288 96,224 C 96,250.51 74.51,272 48,272 C 21.49,272 0,250.51 0,224 C 0,82.615 114.615-32 256-32 Z" data-tags="spinner, loading, busy, wait, wheel" />
<glyph unicode="&#xe00e;" d="M 432,128c-22.58,0-42.96-9.369-57.506-24.415L 158.992,211.336C 159.649,215.462, 160,219.689, 160,224
s-0.351,8.538-1.008,12.663l 215.502,107.751C 389.040,329.369, 409.42,320, 432,320c 44.183,0, 80,35.817, 80,80S 476.183,480, 432,480
s-80-35.817-80-80c0-4.311, 0.352-8.538, 1.008-12.663L 137.506,279.585C 122.96,294.63, 102.58,304, 80,304c-44.183,0-80-35.818-80-80
c0-44.184, 35.817-80, 80-80c 22.58,0, 42.96,9.369, 57.506,24.414l 215.502-107.751C 352.352,56.538, 352,52.311, 352,48
c0-44.184, 35.817-80, 80-80s 80,35.816, 80,80C 512,92.182, 476.183,128, 432,128z" data-tags="share, social" />
<glyph unicode="&#xe001;" d="M 96,416L 416,224L 96,32 z" data-tags="play, media control, audio" />
<glyph unicode="&#xe000;" d="M 512,480 L 512,272 L 432,352 L 336,256 L 288,304 L 384,400 L 304,480 ZM 224,144 L 128,48 L 208-32 L 0-32 L 0,176 L 80,96 L 176,192 Z" data-tags="expand, enlarge, maximize, fullscreen" />
<glyph unicode="&#x20;" horiz-adv-x="256" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -1,949 +0,0 @@
/*!
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. <video class="video-js my-skin-name">
*/
.vjs-default-skin {
color: @main-font-color;
}
/* Custom Icon Font
--------------------------------------------------------------------------------
The control icons are from a custom font. Each icon corresponds to a character
(e.g. "\e001"). Font icons allow for easy scaling and coloring of icons.
*/
@font-face{
font-family: 'VideoJS';
src: url('font/vjs.eot');
src: url('font/vjs.eot?#iefix') format('embedded-opentype'),
url('font/vjs.woff') format('woff'),
url('font/vjs.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
// Icon font character values
@play-icon: "\e001";
@pause-icon: "\e002";
@volume-muted-icon: "\e003";
@volume-low-icon: "\e004";
@volume-mid-icon: "\e005";
@volume-high-icon: "\e006";
@fullscreen-enter-icon: "\e000";
@fullscreen-exit-icon: "\e00b";
@square-icon: "\e009";
@spinner-icon: "\e00a";
@spinner2-icon: "\e00d";
@spinner3-icon: "\e01e";
@spinner4-icon: "\e01f";
@subtitles-icon: "\e00c";
@captions-icon: "\e008";
@share-icon: "\e00e";
/* Base UI Component Classes
--------------------------------------------------------------------------------
*/
/* Slider - used for Volume bar and Seek bar */
.vjs-default-skin .vjs-slider {
/* Replace browser focus hightlight with handle highlight *///
outline: 0;
position: relative;
cursor: pointer;
padding: 0;
.background-color-with-alpha(@slider-background-color, @slider-background-alpha);
}
.vjs-default-skin .vjs-slider:focus {
.box-shadow(0 0 2em #fff);
}
.vjs-default-skin .vjs-slider-handle {
position: absolute;
/* Needed for IE6 *///
left: 0;
top: 0;
}
.vjs-default-skin .vjs-slider-handle:before {
content: @square-icon;
font-family: VideoJS;
font-size: 1em;
line-height: 1;
text-align: center;
text-shadow: 0em 0em 1em #fff;
position: absolute;
top: 0;
left: 0;
/* Rotate the square icon to make a diamond *///
.transform(rotate(-45deg));
}
/* Control Bar
--------------------------------------------------------------------------------
The default control bar that is a container for most of the controls.
*/
.vjs-default-skin .vjs-control-bar {
/* Start hidden *///
display: none;
position: absolute;
/* Place control bar at the bottom of the player box/video.
If you want more margin below the control bar, add more height. *///
bottom: 0;
/* Use left/right to stretch to 100% width of player div *///
left: 0;
right: 0;
/* Height includes any margin you want above or below control items *///
height: 3.0em;
.background-color-with-alpha(@control-bg-color, @control-bg-alpha);
}
/* Show the control bar only once the video has started playing */
.vjs-default-skin.vjs-has-started .vjs-control-bar {
display: block;
/* Visibility needed to make sure things hide in older browsers too. */
visibility: visible;
opacity: 1;
@trans: visibility 0.1s, opacity 0.1s; // Var needed because of comma
.transition(@trans);
}
/* Hide the control bar when the video is playing and the user is inactive */
.vjs-default-skin.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-control-bar {
display: block;
visibility: hidden;
opacity: 0;
@trans: visibility 1.0s, opacity 1.0s;
.transition(@trans);
}
.vjs-default-skin.vjs-controls-disabled .vjs-control-bar {
display: none;
}
.vjs-default-skin.vjs-using-native-controls .vjs-control-bar {
display: none;
}
/* IE8 is flakey with fonts, and you have to change the actual content to force
fonts to show/hide properly.
- "\9" IE8 hack didn't work for this
- Found in XP IE8 from http://modern.ie. Does not show up in "IE8 mode" in IE9
*/
@ie8screen: ~"\0screen";
.vjs-default-skin.vjs-user-inactive.vjs-playing .vjs-control-bar :before {
@media @ie8screen { content: ""; }
}
/* General styles for individual controls. */
.vjs-default-skin .vjs-control {
outline: none;
position: relative;
float: left;
text-align: center;
margin: 0;
padding: 0;
height: 3.0em;
width: 4em;
}
/* FontAwsome button icons */
.vjs-default-skin .vjs-control:before {
font-family: VideoJS;
font-size: 1.5em;
line-height: 2;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
text-align: center;
text-shadow: 1px 1px 1px rgba(0,0,0,0.5);
}
/* Replacement for focus outline */
.vjs-default-skin .vjs-control:focus:before,
.vjs-default-skin .vjs-control:hover:before {
text-shadow: 0em 0em 1em rgba(255, 255, 255, 1);
}
.vjs-default-skin .vjs-control:focus {
/* outline: 0; *///
/* keyboard-only users cannot see the focus on several of the UI elements when
this is set to 0 */
}
/* Hide control text visually, but have it available for screenreaders */
.vjs-default-skin .vjs-control-text {
.hide-visually;
}
/* Play/Pause
--------------------------------------------------------------------------------
*/
.vjs-default-skin .vjs-play-control {
width: 5em;
cursor: pointer;
}
.vjs-default-skin .vjs-play-control:before {
content: @play-icon;
}
.vjs-default-skin.vjs-playing .vjs-play-control:before {
content: @pause-icon;
}
/* Volume/Mute
-------------------------------------------------------------------------------- */
.vjs-default-skin .vjs-mute-control,
.vjs-default-skin .vjs-volume-menu-button {
cursor: pointer;
float: right;
}
.vjs-default-skin .vjs-mute-control:before,
.vjs-default-skin .vjs-volume-menu-button:before {
content: @volume-high-icon;
}
.vjs-default-skin .vjs-mute-control.vjs-vol-0:before,
.vjs-default-skin .vjs-volume-menu-button.vjs-vol-0:before {
content: @volume-muted-icon;
}
.vjs-default-skin .vjs-mute-control.vjs-vol-1:before,
.vjs-default-skin .vjs-volume-menu-button.vjs-vol-1:before {
content: @volume-low-icon;
}
.vjs-default-skin .vjs-mute-control.vjs-vol-2:before,
.vjs-default-skin .vjs-volume-menu-button.vjs-vol-2:before {
content: @volume-mid-icon;
}
.vjs-default-skin .vjs-volume-control {
width: 5em;
float: right;
}
.vjs-default-skin .vjs-volume-bar {
width: 5em;
height: 0.6em;
margin: 1.1em auto 0;
}
.vjs-default-skin .vjs-volume-menu-button .vjs-menu-content {
height: 2.9em;
}
.vjs-default-skin .vjs-volume-level {
position: absolute;
top: 0;
left: 0;
height: 0.5em;
background: @slider-bar-color
url(@slider-bar-pattern)
-50% 0 repeat;
}
.vjs-default-skin .vjs-volume-bar .vjs-volume-handle {
width: 0.5em;
height: 0.5em;
}
.vjs-default-skin .vjs-volume-handle:before {
font-size: 0.9em;
top: -0.2em;
left: -0.2em;
width: 1em;
height: 1em;
}
.vjs-default-skin .vjs-volume-menu-button .vjs-menu .vjs-menu-content {
width: 6em;
left: -4em;
}
/* Progress
--------------------------------------------------------------------------------
*/
.vjs-default-skin .vjs-progress-control {
position: absolute;
left: 0;
right: 0;
width: auto;
font-size: 0.3em;
height: 1em;
/* Set above the rest of the controls. *///
top: -1em;
/* Shrink the bar slower than it grows. *///
.transition(all 0.4s);
}
/* On hover, make the progress bar grow to something that's more clickable.
This simply changes the overall font for the progress bar, and this
updates both the em-based widths and heights, as wells as the icon font */
.vjs-default-skin:hover .vjs-progress-control {
font-size: .9em;
/* Even though we're not changing the top/height, we need to include them in
the transition so they're handled correctly. */
.transition(all 0.2s);
}
/* Box containing play and load progresses. Also acts as seek scrubber. */
.vjs-default-skin .vjs-progress-holder {
height: 100%;
}
/* Progress Bars */
.vjs-default-skin .vjs-progress-holder .vjs-play-progress,
.vjs-default-skin .vjs-progress-holder .vjs-load-progress {
position: absolute;
display: block;
height: 100%;
margin: 0;
padding: 0;
/* Needed for IE6 *///
left: 0;
top: 0;
}
.vjs-default-skin .vjs-play-progress {
/*
Using a data URI to create the white diagonal lines with a transparent
background. Surprisingly works in IE8.
Created using http://www.patternify.com
Changing the first color value will change the bar color.
Also using a paralax effect to make the lines move backwards.
The -50% left position makes that happen.
*/
background: @slider-bar-color
url(@slider-bar-pattern)
-50% 0 repeat;
}
.vjs-default-skin .vjs-load-progress {
background: rgb(100, 100, 100) /* IE8- Fallback */;
background: rgba(255, 255, 255, 0.4);
}
.vjs-default-skin .vjs-seek-handle {
width: 1.5em;
height: 100%;
}
.vjs-default-skin .vjs-seek-handle:before {
padding-top: 0.1em /* Minor adjustment */;
}
/* Time Display
--------------------------------------------------------------------------------
*/
.vjs-default-skin .vjs-time-controls {
font-size: 1em;
/* Align vertically by making the line height the same as the control bar *///
line-height: 3em;
}
.vjs-default-skin .vjs-current-time { float: left; }
.vjs-default-skin .vjs-duration { float: left; }
/* Remaining time is in the HTML, but not included in default design */
.vjs-default-skin .vjs-remaining-time { display: none; float: left; }
.vjs-time-divider { float: left; line-height: 3em; }
/* Fullscreen
--------------------------------------------------------------------------------
*/
.vjs-default-skin .vjs-fullscreen-control {
width: 3.8em;
cursor: pointer;
float: right;
}
.vjs-default-skin .vjs-fullscreen-control:before {
content: @fullscreen-enter-icon;
}
/* Switch to the exit icon when the player is in fullscreen */
.vjs-default-skin.vjs-fullscreen .vjs-fullscreen-control:before {
content: @fullscreen-exit-icon;
}
/* Big Play Button (play button at start)
--------------------------------------------------------------------------------
Positioning of the play button in the center or other corners can be done more
easily in the skin designer. http://designer.videojs.com/
*/
.vjs-default-skin .vjs-big-play-button {
// Calculate total width/height so we're able to center the button
@total-width: @big-play-width + (@big-play-border-width * 2);
@total-height: @big-play-height + (@big-play-border-width * 2);
// Position the button using the absolute-align mixin (bottom of page)
.absolute-align(@big-play-align, @big-play-margin, @total-width);
.absolute-align(@big-play-vertical-align, @big-play-margin, @total-height);
font-size: @big-play-font-size;
display: block;
z-index: 2;
position: absolute;
width: @big-play-width;
height: @big-play-height;
text-align: center;
vertical-align: middle;
cursor: pointer;
opacity: 1;
/* Need a slightly gray bg so it can be seen on black backgrounds *///
.background-color-with-alpha(@big-play-bg-color, @big-play-bg-alpha);
border: @big-play-border-width solid @big-play-border-color;
.border-radius(@big-play-border-radius);
.box-shadow(0px 0px 1em rgba(255, 255, 255, 0.25));
.transition(all 0.4s);
}
/* Optionally center */
.vjs-default-skin.vjs-big-play-centered .vjs-big-play-button {
@total-width: @big-play-width + (@big-play-border-width * 2);
@total-height: @big-play-height + (@big-play-border-width * 2);
.absolute-align(center, @big-play-margin, @total-width);
.absolute-align(middle, @big-play-margin, @total-height);
}
/* Hide if controls are disabled */
.vjs-default-skin.vjs-controls-disabled .vjs-big-play-button {
display: none;
}
/* Hide when video starts playing */
.vjs-default-skin.vjs-has-started .vjs-big-play-button {
display: none;
}
/* Hide on mobile devices. Remove when we stop using native controls
by default on mobile */
.vjs-default-skin.vjs-using-native-controls .vjs-big-play-button {
display: none;
}
.vjs-default-skin:hover .vjs-big-play-button,
.vjs-default-skin .vjs-big-play-button:focus {
outline: 0;
border-color: #fff;
/* IE8 needs a non-glow hover state *///
background-color: rgb(80, 80, 80);
background-color: rgba(50, 50, 50, 0.75);
.box-shadow(0 0 3em #fff);
.transition(all 0s);
}
.vjs-default-skin .vjs-big-play-button:before {
content: @play-icon;
font-family: VideoJS;
/* In order to center the play icon vertically we need to set the line height
to the same as the button height */
line-height: @big-play-height;
text-shadow: 0.05em 0.05em 0.1em #000;
text-align: center /* Needed for IE8 */;
position: absolute;
left: 0;
width: 100%;
height: 100%;
}
/* Loading Spinner
--------------------------------------------------------------------------------
*/
.vjs-loading-spinner {
display: none;
position: absolute;
top: 50%;
left: 50%;
font-size: 4em;
line-height: 1;
width: 1em;
height: 1em;
margin-left: -0.5em;
margin-top: -0.5em;
opacity: 0.75;
.animation(spin 1.5s infinite linear);
}
.vjs-default-skin .vjs-loading-spinner:before {
content: @spinner3-icon;
font-family: VideoJS;
position: absolute;
top: 0;
left: 0;
width: 1em;
height: 1em;
text-align: center;
text-shadow: 0em 0em 0.1em #000;
}
@-moz-keyframes spin {
0% { -moz-transform: rotate(0deg); }
100% { -moz-transform: rotate(359deg); }
}
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(359deg); }
}
@-o-keyframes spin {
0% { -o-transform: rotate(0deg); }
100% { -o-transform: rotate(359deg); }
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(359deg); }
}
/* Menu Buttons (Captions/Subtitles/etc.)
--------------------------------------------------------------------------------
*/
.vjs-default-skin .vjs-menu-button {
float: right;
cursor: pointer;
}
.vjs-default-skin .vjs-menu {
display: none;
position: absolute;
bottom: 0;
left: 0em; /* (Width of vjs-menu - width of button) / 2 */
width: 0em;
height: 0em;
margin-bottom: 3em;
border-left: 2em solid transparent;
border-right: 2em solid transparent;
border-top: 1.55em solid rgb(0, 0, 0); /* Same width top as ul bottom */
border-top-color: rgba(7, 40, 50, 0.5); /* Same as ul background */
}
/* Button Pop-up Menu */
.vjs-default-skin .vjs-menu-button .vjs-menu .vjs-menu-content {
display: block;
padding: 0; margin: 0;
position: absolute;
width: 10em;
bottom: 1.5em; /* Same bottom as vjs-menu border-top */
max-height: 15em;
overflow: auto;
left: -5em; /* Width of menu - width of button / 2 */
.background-color-with-alpha(@control-bg-color, @control-bg-alpha);
.box-shadow(-0.2em -0.2em 0.3em rgba(255, 255, 255, 0.2));
}
.vjs-default-skin .vjs-menu-button:hover .vjs-menu {
display: block;
}
.vjs-default-skin .vjs-menu-button ul li {
list-style: none;
margin: 0;
padding: 0.3em 0 0.3em 0;
line-height: 1.4em;
font-size: 1.2em;
text-align: center;
text-transform: lowercase;
}
.vjs-default-skin .vjs-menu-button ul li.vjs-selected {
background-color: #000;
}
.vjs-default-skin .vjs-menu-button ul li:focus,
.vjs-default-skin .vjs-menu-button ul li:hover,
.vjs-default-skin .vjs-menu-button ul li.vjs-selected:focus,
.vjs-default-skin .vjs-menu-button ul li.vjs-selected:hover {
outline: 0;
color: #111;
.background-color-with-alpha(rgb(255, 255, 255), 0.75);
.box-shadow(0 0 1em rgba(255, 255, 255, 1));
}
.vjs-default-skin .vjs-menu-button ul li.vjs-menu-title {
text-align: center;
text-transform: uppercase;
font-size: 1em;
line-height: 2em;
padding: 0;
margin: 0 0 0.3em 0;
font-weight: bold;
cursor: default;
}
/* Subtitles Button */
.vjs-default-skin .vjs-subtitles-button:before { content: @subtitles-icon; }
/* Captions Button */
.vjs-default-skin .vjs-captions-button:before {
content: @captions-icon;
}
/* Replacement for focus outline */
.vjs-default-skin .vjs-captions-button:focus .vjs-control-content:before,
.vjs-default-skin .vjs-captions-button:hover .vjs-control-content:before {
.box-shadow(0 0 1em rgba(255, 255, 255, 1));
}
/*
REQUIRED STYLES (be careful overriding)
================================================================================
When loading the player, the video tag is replaced with a DIV,
that will hold the video tag or object tag for other playback methods.
The div contains the video playback element (Flash or HTML5) and controls,
and sets the width and height of the video.
** If you want to add some kind of border/padding (e.g. a frame), or special
positioning, use another containing element. Otherwise you risk messing up
control positioning and full window mode. **
*/
.video-js {
background-color: #000;
position: relative;
padding: 0;
/* Start with 10px for base font size so other dimensions can be em based and
easily calculable. */
font-size: @base-font-size;
/* Allow poster to be vertially aligned. */
vertical-align: middle;
/* display: table-cell; */ /*This works in Safari but not Firefox.*/
/* Provide some basic defaults for fonts */
font-weight: normal;
font-style: normal;
/* Avoiding helvetica: issue #376 */
font-family: Arial, sans-serif;
/* Turn off user selection (text highlighting) by default.
The majority of player components will not be text blocks.
Text areas will need to turn user selection back on. */
.user-select(none);
}
/* Playback technology elements expand to the width/height of the containing div
<video> or <object> */
.video-js .vjs-tech {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* Fix for Firefox 9 fullscreen (only if it is enabled). Not needed when
checking fullScreenEnabled. */
.video-js:-moz-full-screen { position: absolute; }
/* Fullscreen Styles */
body.vjs-full-window {
padding: 0;
margin: 0;
height: 100%;
/* Fix for IE6 full-window. http://www.cssplay.co.uk/layouts/fixed.html *///
overflow-y: auto;
}
.video-js.vjs-fullscreen {
position: fixed;
overflow: hidden;
z-index: 1000;
left: 0;
top: 0;
bottom: 0;
right: 0;
width: 100% !important;
height: 100% !important;
/* IE6 full-window (underscore hack) *///
_position: absolute;
}
.video-js:-webkit-full-screen {
width: 100% !important;
height: 100% !important;
}
.video-js.vjs-fullscreen.vjs-user-inactive {
cursor: none;
}
/* Poster Styles */
.vjs-poster {
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: contain;
cursor: pointer;
height: 100%;
margin: 0;
padding: 0;
position: relative;
width: 100%;
}
.vjs-poster img {
display: block;
margin: 0 auto;
max-height: 100%;
padding: 0;
width: 100%;
}
/* Hide the poster when native controls are used otherwise it covers them */
.video-js.vjs-using-native-controls .vjs-poster {
display: none;
}
/* Text Track Styles */
/* Overall track holder for both captions and subtitles */
.video-js .vjs-text-track-display {
text-align: center;
position: absolute;
bottom: 4em;
/* Leave padding on left and right *///
left: 1em;
right: 1em;
}
/* Individual tracks */
.video-js .vjs-text-track {
display: none;
font-size: 1.4em;
text-align: center;
margin-bottom: 0.1em;
/* Transparent black background, or fallback to all black (oldIE) *///
.background-color-with-alpha(rgb(0, 0, 0), 0.5);
}
.video-js .vjs-subtitles { color: #fff /* Subtitles are white */; }
.video-js .vjs-captions { color: #fc6 /* Captions are yellow */; }
.vjs-tt-cue { display: block; }
/* Hide disabled or unsupported controls */
.vjs-default-skin .vjs-hidden { display: none; }
.vjs-lock-showing {
display: block !important;
opacity: 1;
visibility: visible;
}
// MIXINS
// =============================================================================
// Mixins are a LESS feature and are used to add vendor prefixes to CSS rules
// when needed.
// https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow
.box-shadow (@string: 0 0 1em rgba(0, 0, 0, 0.25)) {
/* box-shadow *///
-webkit-box-shadow: @string;
-moz-box-shadow: @string;
box-shadow: @string;
}
// https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius
.border-radius (@string: 5px) {
/* border-radius *///
-webkit-border-radius: @string;
-moz-border-radius: @string;
border-radius: @string;
}
// https://developer.mozilla.org/en-US/docs/Web/CSS/transition
.transition (@string: all 1s linear) {
/* transition *///
-webkit-transition: @string;
-moz-transition: @string;
-o-transition: @string;
transition: @string;
}
// https://developer.mozilla.org/en-US/docs/Web/CSS/transition
.transition-delay (@string: 1s) {
/* transition-delay *///
-webkit-transition-delay: @string;
-moz-transition-delay: @string;
-o-transition-delay: @string;
transition-delay: @string;
}
// https://developer.mozilla.org/en-US/docs/Web/CSS/animation
.animation (@string: spin 1s infinite linear) {
/* animation *///
-webkit-animation: @string;
-moz-animation: @string;
-o-animation: @string;
animation: @string;
}
// https://developer.mozilla.org/en-US/docs/Web/CSS/transform
.transform (@string: rotate(-45deg)) {
/* transform *///
-webkit-transform: @string;
-moz-transform: @string;
-ms-transform: @string;
-o-transform: @string;
transform: @string;
}
// https://developer.mozilla.org/en-US/docs/Web/CSS/user-select
.user-select (@string: none) {
/* user-select *///
-webkit-user-select: @string;
-moz-user-select: @string;
-ms-user-select: @string;
user-select: @string;
}
// Hide something visually but keep available for screen readers.
// http://h5bp.com/v
.hide-visually () {
/* hide-visually *///
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position:
absolute;
width: 1px;
}
// Align an object with absolute positioning
// Used to align the Big Play Button in the corners or center
.absolute-align (@align, @margin, @length) when (@align = top) {
top: @margin;
}
.absolute-align (@align, @margin, @length) when (@align = bottom) {
bottom: @margin;
}
.absolute-align (@align, @margin, @length) when (@align = left) {
left: @margin;
}
.absolute-align (@align, @margin, @length) when (@align = right) {
right: @margin;
}
.absolute-align (@align, @margin, @length) when (@align = center) {
/* Center it horizontally *///
left: 50%;
margin-left: -(@length / 2);
}
.absolute-align (@align, @margin, @length) when (@align = middle) {
/* Center it vertically *///
top: 50%;
margin-top: -(@length / 2);
}
// http://stackoverflow.com/questions/637921/opacity-of-background-but-not-the-text
.background-color-with-alpha (@color, @alpha) {
@rgba: rgba(red(@color), green(@color), blue(@color), @alpha);
/* background-color-with-alpha *///
background-color: @color;
background-color: @rgba;
// No longer using MS filters because they break border radius in IE9
// @argb: argb(@rgba);
// filter: ~"progid:DXImageTransform.Microsoft.gradient(startColorstr=@{argb}, endColorstr=@{argb})";
// -ms-filter: ~"progid:DXImageTransform.Microsoft.gradient(startColorstr=@{argb}, endColorstr=@{argb})";
}
.border-color-with-alpha (@color, @alpha) {
@rgba: rgba(red(@color), green(@color), blue(@color), @alpha);
/* border-color-with-alpha *///
border-color: @color;
border-color: @rgba;
}
// NOTES ON LESS (tracking learnings so we don't forget)
// =============================================================================
// * We want this file to continue to be accessible by people who don't know
// LESS but know CSS. This means finding the balance between using the most
// valuable LESS features (e.g. variables) and keeping it looking like CSS.
// So it's best to avoid advanced LESS features like conditional statements.
// (we're using one for the big play button position because that's a hot
// topic)
//
// * We care about the readability of the CSS output of LESS, which means we
// have to be careful about what features of LESS we use. (if you're building
// your own skin this may not apply)
// 1. Comments inside of rules (strangely) have an extra line added after
// them in the CSS output. To avoid this we can add a LESS comment after
// the CSS comment.
// /* comment *///
//
// 2. In a rule with nested rules, any comments outside of a rule are moved
// to the top of the parent rule. i.e. it might look like:
// /* title of rule 1 */
// /* title of rule 2 */
// .rule1 {}
// .rule2 {}
// This is why we aren't using nested rules inside of the
// vjs-default-skin class.
/* -----------------------------------------------------------------------------
The original source of this file lives at
https://github.com/videojs/video.js/blob/master/src/css/video-js.less */

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

View File

@@ -1,65 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>
This is a custom SVG font generated by IcoMoon.
<iconset grid="16"></iconset>
</metadata>
<defs>
<font id="VideoJS" horiz-adv-x="512" >
<font-face units-per-em="512" ascent="480" descent="-32" />
<missing-glyph horiz-adv-x="512" />
<glyph class="hidden" unicode="&#xf000;" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" />
<glyph unicode="&#xe002;" d="M 64,416L 224,416L 224,32L 64,32zM 288,416L 448,416L 448,32L 288,32z" />
<glyph unicode="&#xe003;" d="M 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" />
<glyph unicode="&#xe004;" d="M 274.51,109.49c-6.143,0-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0,33.941
c 40.55,40.55, 40.55,106.529,0,147.078c-9.373,9.373-9.373,24.569,0,33.941c 9.373,9.372, 24.568,9.372, 33.941,0
c 59.265-59.265, 59.265-155.696,0-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" />
<glyph unicode="&#xe005;" d="M 359.765,64.235c-6.143,0-12.284,2.343-16.971,7.029c-9.372,9.372-9.372,24.568,0,33.941
c 65.503,65.503, 65.503,172.085,0,237.588c-9.372,9.373-9.372,24.569,0,33.941c 9.372,9.371, 24.569,9.372, 33.941,0
C 417.532,335.938, 440,281.696, 440,224c0-57.695-22.468-111.938-63.265-152.735C 372.049,66.578, 365.907,64.235, 359.765,64.235zM 274.51,109.49c-6.143,0-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0,33.941
c 40.55,40.55, 40.55,106.529,0,147.078c-9.373,9.373-9.373,24.569,0,33.941c 9.373,9.372, 24.568,9.372, 33.941,0
c 59.265-59.265, 59.265-155.696,0-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" />
<glyph unicode="&#xe006;" d="M 445.020,18.98c-6.143,0-12.284,2.343-16.971,7.029c-9.372,9.373-9.372,24.568,0,33.941
C 471.868,103.771, 496.001,162.030, 496.001,224c0,61.969-24.133,120.229-67.952,164.049c-9.372,9.373-9.372,24.569,0,33.941
c 9.372,9.372, 24.569,9.372, 33.941,0c 52.885-52.886, 82.011-123.2, 82.011-197.99c0-74.791-29.126-145.104-82.011-197.99
C 457.304,21.323, 451.162,18.98, 445.020,18.98zM 359.765,64.235c-6.143,0-12.284,2.343-16.971,7.029c-9.372,9.372-9.372,24.568,0,33.941
c 65.503,65.503, 65.503,172.085,0,237.588c-9.372,9.373-9.372,24.569,0,33.941c 9.372,9.371, 24.569,9.372, 33.941,0
C 417.532,335.938, 440,281.696, 440,224c0-57.695-22.468-111.938-63.265-152.735C 372.049,66.578, 365.907,64.235, 359.765,64.235zM 274.51,109.49c-6.143,0-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0,33.941
c 40.55,40.55, 40.55,106.529,0,147.078c-9.373,9.373-9.373,24.569,0,33.941c 9.373,9.372, 24.568,9.372, 33.941,0
c 59.265-59.265, 59.265-155.696,0-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" horiz-adv-x="544" />
<glyph unicode="&#xe007;" d="M 256,480L 96,224L 256-32L 416,224 z" />
<glyph unicode="&#xe008;" d="M 0,480 L 687.158,480 L 687.158-35.207 L 0-35.207 L 0,480 z M 622.731,224.638 C 621.878,314.664 618.46,353.922 597.131,381.656 C 593.291,387.629 586.038,391.042 580.065,395.304 C 559.158,410.669 460.593,416.211 346.247,416.211 C 231.896,416.211 128.642,410.669 108.162,395.304 C 101.762,391.042 94.504,387.629 90.242,381.656 C 69.331,353.922 66.349,314.664 65.069,224.638 C 66.349,134.607 69.331,95.353 90.242,67.62 C 94.504,61.22 101.762,58.233 108.162,53.967 C 128.642,38.18 231.896,33.060 346.247,32.207 C 460.593,33.060 559.158,38.18 580.065,53.967 C 586.038,58.233 593.291,61.22 597.131,67.62 C 618.46,95.353 621.878,134.607 622.731,224.638 z M 331.179,247.952 C 325.389,318.401 287.924,359.905 220.901,359.905 C 159.672,359.905 111.54,304.689 111.54,215.965 C 111.54,126.859 155.405,71.267 227.907,71.267 C 285.79,71.267 326.306,113.916 332.701,184.742 L 263.55,184.742 C 260.81,158.468 249.843,138.285 226.69,138.285 C 190.136,138.285 183.435,174.462 183.435,212.92 C 183.435,265.854 198.665,292.886 223.951,292.886 C 246.492,292.886 260.81,276.511 262.939,247.952 L 331.179,247.952 z M 570.013,247.952 C 564.228,318.401 526.758,359.905 459.74,359.905 C 398.507,359.905 350.379,304.689 350.379,215.965 C 350.379,126.859 394.244,71.267 466.746,71.267 C 524.625,71.267 565.14,113.916 571.536,184.742 L 502.384,184.742 C 499.649,158.468 488.682,138.285 465.529,138.285 C 428.971,138.285 422.27,174.462 422.27,212.92 C 422.27,265.854 437.504,292.886 462.785,292.886 C 485.327,292.886 499.649,276.511 501.778,247.952 L 570.013,247.952 z " horiz-adv-x="687.158" />
<glyph unicode="&#xe009;" d="M 64,416L 448,416L 448,32L 64,32z" />
<glyph unicode="&#xe00a;" d="M 192,416A64,64 12780 1 1 320,416A64,64 12780 1 1 192,416zM 327.765,359.765A64,64 12780 1 1 455.765,359.765A64,64 12780 1 1 327.765,359.765zM 416,224A32,32 12780 1 1 480,224A32,32 12780 1 1 416,224zM 359.765,88.235A32,32 12780 1 1 423.765,88.23500000000001A32,32 12780 1 1 359.765,88.23500000000001zM 224.001,32A32,32 12780 1 1 288.001,32A32,32 12780 1 1 224.001,32zM 88.236,88.235A32,32 12780 1 1 152.236,88.23500000000001A32,32 12780 1 1 88.236,88.23500000000001zM 72.236,359.765A48,48 12780 1 1 168.236,359.765A48,48 12780 1 1 72.236,359.765zM 28,224A36,36 12780 1 1 100,224A36,36 12780 1 1 28,224z" />
<glyph unicode="&#xe00b;" d="M 224,192 L 224-16 L 144,64 L 48-32 L 0,16 L 96,112 L 16,192 ZM 512,432 L 416,336 L 496,256 L 288,256 L 288,464 L 368,384 L 464,480 Z" />
<glyph unicode="&#xe00c;" d="M 256,448 C 397.385,448 512,354.875 512,240 C 512,125.124 397.385,32 256,32 C 242.422,32 229.095,32.867 216.088,34.522 C 161.099-20.467 95.463-30.328 32-31.776 L 32-18.318 C 66.268-1.529 96,29.052 96,64 C 96,68.877 95.621,73.665 94.918,78.348 C 37.020,116.48 0,174.725 0,240 C 0,354.875 114.615,448 256,448 Z" />
<glyph unicode="&#xe00d;" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,352
c 70.692,0, 128-57.308, 128-128s-57.308-128-128-128s-128,57.308-128,128S 185.308,352, 256,352z M 408.735,71.265
C 367.938,30.468, 313.695,8, 256,8c-57.696,0-111.938,22.468-152.735,63.265C 62.468,112.062, 40,166.304, 40,224
c0,57.695, 22.468,111.938, 63.265,152.735l 33.941-33.941c0,0,0,0,0,0c-65.503-65.503-65.503-172.085,0-237.588
C 168.937,73.475, 211.125,56, 256,56c 44.874,0, 87.062,17.475, 118.794,49.206c 65.503,65.503, 65.503,172.084,0,237.588l 33.941,33.941
C 449.532,335.938, 472,281.695, 472,224C 472,166.304, 449.532,112.062, 408.735,71.265z" />
<glyph unicode="&#xe01e;" d="M 512,224c-0.639,33.431-7.892,66.758-21.288,97.231c-13.352,30.5-32.731,58.129-56.521,80.96
c-23.776,22.848-51.972,40.91-82.492,52.826C 321.197,466.979, 288.401,472.693, 256,472c-32.405-0.641-64.666-7.687-94.167-20.678
c-29.524-12.948-56.271-31.735-78.367-54.788c-22.112-23.041-39.58-50.354-51.093-79.899C 20.816,287.104, 15.309,255.375, 16,224
c 0.643-31.38, 7.482-62.574, 20.067-91.103c 12.544-28.55, 30.738-54.414, 53.055-75.774c 22.305-21.377, 48.736-38.252, 77.307-49.36
C 194.988-3.389, 225.652-8.688, 256-8c 30.354,0.645, 60.481,7.277, 88.038,19.457c 27.575,12.141, 52.558,29.74, 73.183,51.322
c 20.641,21.57, 36.922,47.118, 47.627,74.715c 6.517,16.729, 10.94,34.2, 13.271,51.899c 0.623-0.036, 1.249-0.060, 1.881-0.060
c 17.673,0, 32,14.326, 32,32c0,0.898-0.047,1.786-0.119,2.666L 512,223.999 z M 461.153,139.026c-11.736-26.601-28.742-50.7-49.589-70.59
c-20.835-19.905-45.5-35.593-72.122-45.895C 312.828,12.202, 284.297,7.315, 256,8c-28.302,0.649-56.298,6.868-81.91,18.237
c-25.625,11.333-48.842,27.745-67.997,47.856c-19.169,20.099-34.264,43.882-44.161,69.529C 51.997,169.264, 47.318,196.729, 48,224
c 0.651,27.276, 6.664,54.206, 17.627,78.845c 10.929,24.65, 26.749,46.985, 46.123,65.405c 19.365,18.434, 42.265,32.935, 66.937,42.428
C 203.356,420.208, 229.755,424.681, 256,424c 26.25-0.653, 52.114-6.459, 75.781-17.017c 23.676-10.525, 45.128-25.751, 62.812-44.391
c 17.698-18.629, 31.605-40.647, 40.695-64.344C 444.412,274.552, 448.679,249.219, 448,224l 0.119,0 c-0.072-0.88-0.119-1.768-0.119-2.666
c0-16.506, 12.496-30.087, 28.543-31.812C 473.431,172.111, 468.278,155.113, 461.153,139.026z" />
<glyph unicode="&#xe01f;" d="M 256,480 C 116.626,480 3.271,368.619 0.076,230.013 C 3.036,350.945 94.992,448 208,448 C 322.875,448 416,347.712 416,224 C 416,197.49 437.49,176 464,176 C 490.51,176 512,197.49 512,224 C 512,365.385 397.385,480 256,480 ZM 256-32 C 395.374-32 508.729,79.381 511.924,217.987 C 508.964,97.055 417.008,0 304,0 C 189.125,0 96,100.288 96,224 C 96,250.51 74.51,272 48,272 C 21.49,272 0,250.51 0,224 C 0,82.615 114.615-32 256-32 Z" />
<glyph unicode="&#xe00e;" d="M 432,128c-22.58,0-42.96-9.369-57.506-24.415L 158.992,211.336C 159.649,215.462, 160,219.689, 160,224
s-0.351,8.538-1.008,12.663l 215.502,107.751C 389.040,329.369, 409.42,320, 432,320c 44.183,0, 80,35.817, 80,80S 476.183,480, 432,480
s-80-35.817-80-80c0-4.311, 0.352-8.538, 1.008-12.663L 137.506,279.585C 122.96,294.63, 102.58,304, 80,304c-44.183,0-80-35.818-80-80
c0-44.184, 35.817-80, 80-80c 22.58,0, 42.96,9.369, 57.506,24.414l 215.502-107.751C 352.352,56.538, 352,52.311, 352,48
c0-44.184, 35.817-80, 80-80s 80,35.816, 80,80C 512,92.182, 476.183,128, 432,128z" />
<glyph unicode="&#xe001;" d="M 96,416L 416,224L 96,32 z" />
<glyph unicode="&#xe000;" d="M 512,480 L 512,272 L 432,352 L 336,256 L 288,304 L 384,400 L 304,480 ZM 224,144 L 128,48 L 208-32 L 0-32 L 0,176 L 80,96 L 176,192 Z" />
<glyph unicode="&#x20;" horiz-adv-x="256" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

View File

@@ -1,1075 +0,0 @@
/*
OpenSeaDragonAnnotation v1.0 (http://)
Copyright (C) 2014 CHS (Harvard University), Daniel Cebrián Robles and Phil Desenne
License: https://github.com/CtrHellenicStudies/OpenSeaDragonAnnotation/blob/master/License.rst
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
(function($) {
$.Viewer.prototype.annotation = function(options) {
//-- wait for plugins --//
var wrapper = jQuery('.annotator-wrapper').parent()[0],
annotator = jQuery.data(wrapper, 'annotator'),
self = this,
isOpenViewer = false;
/**
* Sets up a call so that every time the OpenSeaDragon instance is opened
* it triggers the annotations to be redrawn.
*/
this.addHandler("open", function() {
isOpenViewer = true;
if (typeof self.annotationInstance!='undefined')
self.annotationInstance.refreshDisplay();
});
annotator
/**
* This function is called once annotator has loaded the annotations.
* It will then wait until the OSD instance has loaded to start drawing
* the annotations.
* @param Array annotations list of annotations from annotator instance
*/
.subscribe("annotationsLoaded", function (annotations){
if (!self.annotationInstance) {
// annotation instance should include the OSD item and annotator
self.annotationInstance = new $._annotation({
viewer: self,
annotator: annotator,
});
// this collection of items is included as an item of annotator so
// that there is a method to communicate back and forth.
annotator.osda = self.annotationInstance;
// Because it takes a while for both OSD to open and for annotator
// to get items from the backend, we wait until we get the "open" call
function refreshDisplay(){
if(!isOpenViewer){
setTimeout(refreshDisplay,200);
}else{
self.annotationInstance.refreshDisplay();
}
}
refreshDisplay();
} else {
self.annotationInstance.refreshDisplay();
}
});
};
/**
* Instance of the annotation package including OSD and Annotator
* @constructor
*/
$._annotation = function(options) {
// options
options = options || {};
if (!options.viewer) {
throw new Error("A viewer must be specified.");
}
// variables
this.viewer = options.viewer;
this.annotator = options.annotator;
this.options = options;
this.isAnnotating = false; // If the user is annotating
this.isDrawing = false; // if the user is drawing something
this.rectPosition = undefined;
// Init
this.init();
};
//-- Methods
$._annotation.prototype = {
/**
* This function makes sure that the OSD buttons are created, that the
* panning and zooming functionality is created and the annotation events.
*/
init: function(){
var viewer = this.viewer;
// create Buttons
this._createNewButton();
/* canvas Events */
// Bind canvas functions
var onCanvasMouseDown = this.__bind(this._onCanvasMouseDown,this);
var onCanvasMouseMove = this.__bind(this._onCanvasMouseMove,this);
var onDocumentMouseUp = this.__bind(this._onDocumentMouseUp,this);
// Add canvas events
$.addEvent(viewer.canvas, "mousedown", onCanvasMouseDown, true);
$.addEvent(viewer.canvas, "mousemove", onCanvasMouseMove, true);
$.addEvent(document, "mouseup", onDocumentMouseUp, true);
// Viewer events
var self = this;
},
/**
* This function is called when the user changed from panning/zooming mode to
* annotation creation mode. It allows the annotator to accept the creation of
* a new annotation.
*/
newAnnotation:function(){
var annotator = this.annotator;
// This variable tells editor that we want create an image annotation
annotator.editor.OpenSeaDragon = this.viewer.id;
// allows the adder to actually show up
annotator.adder.show();
// takes into account the various wrappers and instances to put the shape
// over the correct place.
this._setOverShape(annotator.adder);
// Open a new annotator dialog
annotator.onAdderClick();
},
/**
* This function simply allows the editor to pop up with the given annotation.
* @param {Object} annotation The annotation item from the backend server.
* @param {TinyMCEEditor} editor The item that pops up when you edit an annotation.
*/
editAnnotation: function(annotation,editor){
// Stupid check: is the annotation you're trying to edit an image?
if (this._isOpenSeaDragon(annotation)){
var editor = editor || this.annotator.editor;
// set the editor over the highlighted element
this._setOverShape(editor.element);
editor.checkOrientation();
// makes sure that we are making an image annotation
editor.OpenSeaDragon = this.viewer.id;
}
},
/**
* This function gets the annotations from the last annotator query and sorts
* them and draws them onto the OpenSeaDragon instance. It also publishes
* a notification in case the colorize the annotations.
*/
refreshDisplay: function(){
var allannotations = this.annotator.plugins['Store'].annotations;
var annotator = this.annotator;
// Sort the annotations by date
this._sortByDate(allannotations);
// remove all of the overlays
this.viewer.drawer.clearOverlays();
for (var item in allannotations) {
var an = allannotations[item];
// check if the annotation is an OpenSeaDragon annotation
if (this._isOpenSeaDragon(an)){
this.drawRect(an);
}
}
// if the colored highlights by tags plugin it is notified to colorize
annotator.publish('externalCallToHighlightTags', [an]);
},
/**
* This function get notified every time we switch from panning/zooming mode onto
* annotation creation mode.
* @param {Event} e This is the event passed in from the OSD buttons.
*/
modeAnnotation:function(e){
this._reset();
var viewer = this.viewer;
if (!this.isAnnotating){
// When annotating, the cursor turns into a crosshair and there is a
// green border around the OSD instance.
jQuery('.openseadragon1').css('cursor', 'crosshair');
jQuery('.openseadragon1').css('border', '2px solid rgb(51,204,102)');
e.eventSource.imgGroup.src = this.resolveUrl( viewer.prefixUrl,"newan_hover.png");
e.eventSource.imgRest.src = this.resolveUrl( viewer.prefixUrl,"newan_hover.png");
e.eventSource.imgHover.src = this.resolveUrl( viewer.prefixUrl,"newan_grouphover.png");
}else{
// Otherwise, the cursor is a cross with four arrows to indicate movement
jQuery('.openseadragon1').css('cursor', 'all-scroll');
jQuery('.openseadragon1').css('border', 'inherit');
e.eventSource.imgGroup.src = this.resolveUrl( viewer.prefixUrl,"newan_grouphover.png");
e.eventSource.imgRest.src = this.resolveUrl( viewer.prefixUrl,"newan_rest.png");
e.eventSource.imgHover.src = this.resolveUrl( viewer.prefixUrl,"newan_hover.png");
}
// toggles the annotating flag
this.isAnnotating = !this.isAnnotating?true:false;
},
/**
* This function takes in an annotation and draws the box indicating the area
* that has been annotated.
* @param {Object} an Annotation item from the list in the Annotator instance.
*/
drawRect:function(an){
// Stupid check: Does this annotation actually have an area of annotation
if (typeof an.rangePosition!='undefined'){
// Sets up the visual aspects of the area for the user
var span = document.createElement('span');
var rectPosition = an.rangePosition;
span.className = "annotator-hl";
// outline and border below create a double line one black and one white
// so to be able to differentiate when selecting dark or light images
span.style.border = '2px solid rgb(255, 255, 255)';
span.style.outline = '2px solid rgb(0, 0, 0)';
span.style.background = 'rgba(0,0,0,0)';
// Adds listening items for the viewer and editor
var onAnnotationMouseMove = this.__bind(this._onAnnotationMouseMove,this);
var onAnnotationClick = this.__bind(this._onAnnotationClick,this);
$.addEvent(span, "mousemove", onAnnotationMouseMove, true);
$.addEvent(span, "click", onAnnotationClick, true);
// Set the object in the div
jQuery.data(span, 'annotation', an);
// Add the highlights to the annotation
an.highlights = jQuery(span);
// Sends the element created to the proper location within the OSD instance
var olRect = new OpenSeadragon.Rect(rectPosition.left, rectPosition.top, rectPosition.width, rectPosition.height);
return this.viewer.drawer.addOverlay({
element: span,
location: olRect,
placement: OpenSeadragon.OverlayPlacement.TOP_LEFT
});
}
return false;
},
/**
* This changes the variable rectPosition to the proper location based on
* screen coordinates and OSD image coordinates.
*/
setRectPosition:function(){
// Get the actual locations of the rectangle
var left = parseInt(this.rect.style.left);
var top = parseInt(this.rect.style.top);
var width = parseInt(this.rect.style.left) + parseInt(this.rect.style.width);
var height = parseInt(this.rect.style.top) + parseInt(this.rect.style.height);
var startPoint = new $.Point(left,top);
var endPoint = new $.Point(width,height);
// return the proper value of the rectangle
this.rectPosition = {left:this._physicalToLogicalXY(startPoint).x,
top:this._physicalToLogicalXY(startPoint).y,
width:this._physicalToLogicalXY(endPoint).x - this._physicalToLogicalXY(startPoint).x,
height:this._physicalToLogicalXY(endPoint).y - this._physicalToLogicalXY(startPoint).y
};
},
/* Handlers */
/**
* When the user starts clicking this will create a rectangle that will be a
* temporary position that is to be later scaled via dragging
* @param {Event} event The actual action of clicking down.
*/
_onCanvasMouseDown: function(event) {
// action is ONLY performed if we are in annotation creation mode
if (this.isAnnotating){
var viewer = this.viewer;
event.preventDefault();
// reset the display
this._reset();
// set mode drawing
this.isDrawing = true;
// Create rect element
var mouse = $.getMousePosition( event );
var elementPosition = $.getElementPosition(viewer.canvas);
var position = mouse.minus( elementPosition );
viewer.innerTracker.setTracking(false);
this.rect = document.createElement('div');
this.rect.style.background = 'rgba(0,0,0,0)';
// outline and border below create a double line one black and one white
// so to be able to differentiate when selecting dark or light images
this.rect.style.border = '2px solid rgb(255, 255, 255)';
this.rect.style.outline = '2px solid rgb(0, 0, 0)';
this.rect.style.position = 'absolute';
this.rect.className = 'DrawingRect';
// set the initial position
this.rect.style.top = position.y + "px";
this.rect.style.left = position.x + "px";
this.rect.style.width = "1px";
this.rect.style.height = "1px";
// save the start Position
this.startPosition = position;
// save rectPosition as initial rectangle parameter to Draw in the canvas
this.setRectPosition();
// append Child to the canvas
viewer.canvas.appendChild(this.rect);
}
},
/**
* When the user has clicked and is now dragging to create an annotation area,
* the following function resizes the area selected.
* @param {Event} event The actual action of dragging every time it is dragged.
*/
_onCanvasMouseMove: function(event) {
// of course, this only runs when we are in annotation creation mode and
// when the user has clicked down (and is therefore drawing the rectangle)
if (this.isAnnotating && this.isDrawing){
var viewer = this.viewer;
// Calculate the new end position
var mouse = $.getMousePosition( event );
var elementPosition = $.getElementPosition(viewer.canvas);
var endPosition = mouse.minus( elementPosition );
// retrieve start position
var startPosition = this.startPosition;
var newWidth= endPosition.x-startPosition.x;
var newHeight =endPosition.y-startPosition.y;
// Set new position
this.rect.style.width = (newWidth < 0) ? (-1*newWidth) + 'px' : newWidth + 'px';
this.rect.style.left = (newWidth < 0) ? (startPosition.x + newWidth) + 'px' : startPosition.x + 'px';
this.rect.style.height = (newHeight < 0) ? (-1*newHeight) + 'px' : newHeight + 'px';
this.rect.style.top = (newHeight < 0) ? (startPosition.y + newHeight) + 'px' : startPosition.y + 'px';
// Modify the rectPosition with the new this.rect values
this.setRectPosition();
// Show adder and hide editor
this.annotator.editor.element[0].style.display = 'none';
this._setOverShape(this.annotator.adder);
}
},
/**
* This function will finish drawing the rectangle, get its current position
* and then open up the editor to make the annotation.
*/
_onDocumentMouseUp: function() {
// Stupid check: only do it when in annotation creation mode and
// when the user has begun making a rectangle over the annotation area
if (this.isAnnotating && this.isDrawing){
var viewer = this.viewer;
viewer.innerTracker.setTracking(true);
this.isDrawing = false;
// Set the new position for the rectangle
this.setRectPosition();
// Open Annotator editor
this.newAnnotation();
// Hide adder and show editor
this.annotator.editor.element[0].style.display = 'block';
this._setOverShape(this.annotator.editor.element);
this.annotator.editor.checkOrientation();
}
},
/**
* This function will trigger the viewer to show up whenever an item is hovered
* over and will cause the background color of the area to change a bit.
* @param {Event} event The actual action of moving the mouse over an element.
*/
_onAnnotationMouseMove: function(event){
var annotator = this.annotator;
var elem = jQuery(event.target).parents('.annotator-hl').andSelf();
// if there is a opened annotation then show the new annotation mouse over
if (typeof annotator!='undefined' && elem.hasClass("annotator-hl") && !this.isDrawing){
// hide the last open viewer
annotator.viewer.hide();
// get the annotation over the mouse
var annotations = jQuery(event.target.parentNode).find('.annotator-hl').map(function() {
var self = jQuery(this);
var offset = self.offset();
var l = offset.left;
var t = offset.top;
var h = self.height();
var w = self.width();
var x = $.getMousePosition(event).x;
var y = $.getMousePosition(event).y;
var maxx = l + w;
var maxy = t + h;
// if the current position of the mouse is within the bounds of an area
// change the background of that area to a light yellow to simulate
// a hover. Otherwise, keep it translucent.
this.style.background = (y <= maxy && y >= t) && (x <= maxx && x >= l)?
'rgba(255, 255, 10, 0.05)':'rgba(0, 0, 0, 0)';
return (y <= maxy && y >= t) && (x <= maxx && x >= l)? jQuery(this).data("annotation") : null;
});
// show the annotation in the viewer
var mousePosition = {
top:$.getMousePosition(event).y,
left:$.getMousePosition(event).x,
};
// if the user is hovering over multiple annotation areas,
// they will be stacked as usual
if (annotations.length>0) annotator.showViewer(jQuery.makeArray(annotations), mousePosition);
}
},
/**
* This function will zoom/pan the user into the bounding area of the annotation.
* @param {Event} event The actual action of clicking down within an annotation area.
*/
_onAnnotationClick: function(event){
// gets the annotation from the data stored in the element
var an = jQuery.data(event.target, 'annotation');
// gets the bound within the annotation data
var bounds = typeof an.bounds!='undefined'?an.bounds:{};
var currentBounds = this.viewer.drawer.viewport.getBounds();
// if the area is not already panned and zoomed in to the correct area
if (typeof bounds.x!='undefined') currentBounds.x = bounds.x;
if (typeof bounds.y!='undefined') currentBounds.y = bounds.y;
if (typeof bounds.width!='undefined') currentBounds.width = bounds.width;
if (typeof bounds.height!='undefined') currentBounds.height = bounds.height;
// change the zoom to the saved parameter
this.viewer.drawer.viewport.fitBounds(currentBounds);
},
/* Utilities */
/**
* This function will return an array of sorted items
* @param {Array} annotations List of annotations from annotator instance.
* @param {String} type Either 'asc' for ascending or 'desc' for descending
*/
_sortByDate: function (annotations,type){
var type = type || 'asc'; // asc => The value [0] will be the most recent date
annotations.sort(function(a,b){
// gets the date from when they were last updated
a = new Date(typeof a.updated!='undefined'?createDateFromISO8601(a.updated):'');
b = new Date(typeof b.updated!='undefined'?createDateFromISO8601(b.updated):'');
// orders them based on type passed in
if (type == 'asc')
return b<a?-1:b>a?1:0;
else
return a<b?-1:a>b?1:0;
});
},
/**
* This function creates the button that will switch back and forth between
* annotation creation mode and panning/zooming mode.
*/
_createNewButton:function(){
var viewer = this.viewer;
var onFocusHandler = $.delegate( this, onFocus );
var onBlurHandler = $.delegate( this, onBlur );
var onModeAnnotationHandler = $.delegate( this, this.modeAnnotation );
/* Buttons */
var viewer = this.viewer;
var self = this;
viewer.modeAnnotation = new $.Button({
element: viewer.modeAnnotation ? $.getElement( viewer.modeAnnotation ) : null,
clickTimeThreshold: viewer.clickTimeThreshold,
clickDistThreshold: viewer.clickDistThreshold,
tooltip: "New Annotation",
srcRest: self.resolveUrl( viewer.prefixUrl,"newan_rest.png"),
srcGroup: self.resolveUrl( viewer.prefixUrl,"newan_grouphover.png"),
srcHover: self.resolveUrl( viewer.prefixUrl,"newan_hover.png"),
srcDown: self.resolveUrl( viewer.prefixUrl,"newan_pressed.png"),
onRelease: onModeAnnotationHandler,
onFocus: onFocusHandler,
onBlur: onBlurHandler
});
//- Wrapper Annotation Menu
viewer.wrapperAnnotation = new $.ButtonGroup({
buttons: [
viewer.modeAnnotation,
],
clickTimeThreshold: viewer.clickTimeThreshold,
clickDistThreshold: viewer.clickDistThreshold
});
// area makes sure that the annotation button only appears when everyone is
// allowed to annotate or if you are an instructor
if(this.options.viewer.annotation_mode == "everyone" || this.options.viewer.flags){
/* Set elements to the control menu */
viewer.annotatorControl = viewer.wrapperAnnotation.element;
if( viewer.toolbar ){
viewer.toolbar.addControl(
viewer.annotatorControl,
{anchor: $.ControlAnchor.BOTTOM_RIGHT}
);
}else{
viewer.addControl(
viewer.annotatorControl,
{anchor: $.ControlAnchor.TOP_LEFT}
);
}
}
},
/**
* This function makes sure that if you're switching to panning/zooming mode,
* the last rectangle you drew (but didn't save) gets destroyed.
*/
_reset: function(){
// Find and remove DrawingRect. This is the previous rectangle
this._removeElemsByClass('DrawingRect',this.viewer.canvas);
// Show adder and hide editor
this.annotator.editor.element[0].style.display = 'none';
},
/**
* This function binds the function to the object it was created from
* @param {function} fn This is the function you want to apply
* @param {Object} me This is the object you should pass it to (usually itself)
*/
__bind: function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
/**
* Remove all the elements with a given name inside "inElement" to maintain
* a limited scope.
* @param {String} className Class that should be removed
* @param {HTMLElement} inElement Element in which classes should be removed
*/
_removeElemsByClass: function(className,inElement){
var className = className || '';
var inElement = inElement || {};
divs = inElement.getElementsByClassName(className);
for(var i = 0; i < divs.length; i++) {
divs[i].remove();
}
},
/**
* Detect if the annotation is an image annotation and there's a target, open
* OSD instance.
* @param {Object} an Annotation from the Annotator instance
*/
_isOpenSeaDragon: function (an){
var annotator = this.annotator;
var rp = an.rangePosition;
// Makes sure OSD exists and that annotation is an image annotation
// with a position in the OSD instance
var isOpenSeaDragon = (typeof annotator.osda != 'undefined');
var isContainer = (typeof an.target!='undefined' && an.target.container==this.viewer.id );
var isImage = (typeof an.media!='undefined' && an.media=='image');
var isRP = (typeof rp!='undefined');
var isSource = false;
// Though it would be better to store server ids of images in the annotation that
// would require changing annotations that were already made, instead we check if
// the id is a substring of the thumbnail, which according to OpenSeaDragon API should be the case.
var sourceId = this.viewer.source['@id'];
// code runs on annotation creation before thumbnail is created
var targetThumb = an.target ? an.target.thumb : false;
if (isContainer) {
// reason why this is okay is that we are trying to ascertain that the annotation
// is related to the image drawn. If thumbnail attribute is empty it means the annotation
// was just created and should still be considered an annotation of this image.
isSource = targetThumb ? (targetThumb.indexOf(sourceId) !== -1) : true;
}
return (isOpenSeaDragon && isContainer && isImage && isRP && isSource);
},
/* Annotator Utilities */
/**
* Makes sure that absolute x and y values for overlayed section are
* calculated to match area within OSD instance
* @param {HTMLElement} elem Element where shape is overlayed
*/
_setOverShape: function(elem){
// Calculate Point absolute positions
var rectPosition = this.rectPosition || {};
var startPoint = this._logicalToPhysicalXY(new $.Point(rectPosition.left,rectPosition.top));
var endPoint = this._logicalToPhysicalXY(new $.Point(rectPosition.left + rectPosition.width,rectPosition.top + rectPosition.height));
// Calculate Point absolute positions
var wrapper = jQuery('.annotator-wrapper')[0];
var positionAnnotator = $.getElementPosition(wrapper);
var positionCanvas = $.getElementPosition(this.viewer.canvas);
var positionAdder = {};
// Fix with positionCanvas based on annotator wrapper and OSD area
startPoint = startPoint.plus(positionCanvas);
endPoint = endPoint.plus(positionCanvas);
elem[0].style.display = 'block'; // Show the adder
positionAdder.left = (startPoint.x - positionAnnotator.x) + (endPoint.x - startPoint.x) / 2;
positionAdder.top = (startPoint.y - positionAnnotator.y) + (endPoint.y - startPoint.y) / 2; // It is not necessary fix with - positionAnnotator.y
elem.css(positionAdder);
},
resolveUrl: function( prefix, url ) {
return prefix ? prefix + url : url;
},
/* Canvas Utilities */
/**
* Given a point of x and y values in pixels it will return a point with
* percentages in relation to the Image object
* @param {$.Point} point Canvas relative coordinates in pixels
* @return {$.Point} Returns Image relative percentages
*/
_physicalToLogicalXY: function(point){
var point = typeof point!='undefined'?point:{};
var boundX = this.viewer.viewport.getBounds(true).x;
var boundY = this.viewer.viewport.getBounds(true).y;
var boundWidth = this.viewer.viewport.getBounds(true).width;
var boundHeight = this.viewer.viewport.getBounds(true).height;
var containerSizeX = this.viewer.viewport.getContainerSize().x;
var containerSizeY = this.viewer.viewport.getContainerSize().y;
var x = typeof point.x!='undefined'?point.x:0;
var y = typeof point.y!='undefined'?point.y:0;
x = boundX + ((x / containerSizeX) * boundWidth);
y = boundY + ((y / containerSizeY) * boundHeight);
return new $.Point(x,y);
},
/**
* Given values in percentage relatives to the image it will return a point in
* pixels related to the canvas element.
* @param {$.Point} point Image relative percentages
* @return {$.Point} Returns canvas relative coordinates in pixels
*/
_logicalToPhysicalXY: function(point){
var point = typeof point!='undefined'?point:{};
var boundX = this.viewer.viewport.getBounds(true).x;
var boundY = this.viewer.viewport.getBounds(true).y;
var boundWidth = this.viewer.viewport.getBounds(true).width;
var boundHeight = this.viewer.viewport.getBounds(true).height;
var containerSizeX = this.viewer.viewport.getContainerSize().x;
var containerSizeY = this.viewer.viewport.getContainerSize().y;
var x = typeof point.x!='undefined'?point.x:0;
var y = typeof point.y!='undefined'?point.y:0;
x = (x - boundX) * containerSizeX / boundWidth;
y = (y - boundY) * containerSizeY / boundHeight;
return new $.Point(x,y);
},
}
/* General functions */
/**
* initiates an animation to hide the controls
*/
function beginControlsAutoHide( viewer ) {
if ( !viewer.autoHideControls ) {
return;
}
viewer.controlsShouldFade = true;
viewer.controlsFadeBeginTime =
$.now() +
viewer.controlsFadeDelay;
window.setTimeout( function(){
scheduleControlsFade( viewer );
}, viewer.controlsFadeDelay );
}
/**
* stop the fade animation on the controls and show them
*/
function abortControlsAutoHide( viewer ) {
var i;
viewer.controlsShouldFade = false;
for ( i = viewer.controls.length - 1; i >= 0; i-- ) {
viewer.controls[ i ].setOpacity( 1.0 );
}
}
function onFocus(){
abortControlsAutoHide( this.viewer );
}
function onBlur(){
beginControlsAutoHide( this.viewer );
}
})(OpenSeadragon);
//----------------Plugin for Annotator to setup OpenSeaDragon----------------//
Annotator.Plugin.OpenSeaDragon = (function(_super) {
__extends(OpenSeaDragon, _super);
/**
* Creates an instance of the plugin that interacts with OpenSeaDragon.
* @constructor
*/
function OpenSeaDragon() {
this.pluginSubmit = __bind(this.pluginSubmit, this);
_ref = OpenSeaDragon.__super__.constructor.apply(this, arguments);
// To facilitate calling items, we want to be able to get the index of a value
this.__indexOf = [].indexOf;
if(!this.__indexOf){
// Basically you iterate through every item on the list, if it matches
// the item you are looking for return the current index, otherwise return -1
this.__indexOf = function(item) {
for (var i = 0, l = this.length; i < l; i++) {
if (i in this && this[i] === item)
return i;
}
return -1;
}
}
return _ref;
}
OpenSeaDragon.prototype.field = null;
OpenSeaDragon.prototype.input = null;
/**
* This function initiates the editor that will apear when you edit/create an
* annotation and the viewer that appears when you hover over an item.
*/
OpenSeaDragon.prototype.pluginInit = function() {
// Check that annotator is working
if (!Annotator.supported()) {
return;
}
//-- Editor
this.field = this.annotator.editor.addField({
id: 'osd-input-rangePosition-annotations',
type: 'input', // options (textarea,input,select,checkbox)
submit: this.pluginSubmit,
EditOpenSeaDragonAn: this.EditOpenSeaDragonAn
});
// Modify the element created with annotator to be an invisible span
var select = '<li><span id="osd-input-rangePosition-annotations"></span></li>';
var newfield = Annotator.$(select);
Annotator.$(this.field).replaceWith(newfield);
this.field=newfield[0];
//-- Listener for OpenSeaDragon Plugin
this.initListeners();
return this.input = $(this.field).find(':input');
}
/**
* This function is called by annotator whenever user hits the "Save" Button. It will
* first check to see if the user is editing or creating and then save the
* metadata for the image in an object that will be passed to the backend.
*/
OpenSeaDragon.prototype.pluginSubmit = function(field, annotation) {
// Select the new JSON for the Object to save
if (this.EditOpenSeaDragonAn()){
var annotator = this.annotator;
var osda = annotator.osda;
var position = osda.rectPosition || {};
var isNew = typeof annotation.media=='undefined';
if(isNew){
// if it's undefined, we know it's an image because the editor within
// the OSD instance was open
if (typeof annotation.media == 'undefined') annotation.media = "image"; // - media
annotation.target = annotation.target || {}; // - target
annotation.target.container = osda.viewer.id || ""; // - target.container
// Save source url
var source = osda.viewer.source;
var tilesUrl = typeof source.tilesUrl!='undefined'?source.tilesUrl:'';
var functionUrl = typeof source.getTileUrl!='undefined'?source.getTileUrl():'';
annotation.target.src = tilesUrl!=''?tilesUrl:('' + functionUrl).replace(/\s+/g, ' '); // - target.src (media source)
annotation.target.ext = source.fileFormat || ""; // - target.ext (extension)
// Gets the bounds in order to save them for zooming in and highlight properties
annotation.bounds = osda.viewer.drawer.viewport.getBounds() || {}; // - bounds
var finalimagelink = source["@id"].replace("/info.json", "");
var highlightX = Math.round(position.left * source["width"]);
var highlightY = Math.round(position.top * source["width"]);
var highlightWidth = Math.round(position.width * source["width"]);
var highlightHeight = Math.round(position.height * source["width"]);
// creates a link to the OSD server that contains the image to get
// the thumbnail of the selected portion of the image
annotation.target.thumb = finalimagelink + "/" + highlightX + "," + highlightY + "," + highlightWidth + "," + highlightHeight + "/full/0/native." + source["formats"][0];
if(isNew) annotation.rangePosition = position || {}; // - rangePosition
// updates the dates associated with creation and update
annotation.updated = new Date().toISOString(); // - updated
if (typeof annotation.created == 'undefined')
annotation.created = annotation.updated; // - created
}
}
return annotation.media;
};
//------ Methods ------//
/**
* Detect if we are creating or editing an OpenSeaDragon annotation
*/
OpenSeaDragon.prototype.EditOpenSeaDragonAn = function (){
var wrapper = $('.annotator-wrapper').parent()[0],
annotator = window.annotator = $.data(wrapper, 'annotator'),
isOpenSeaDragon = (typeof annotator.osda != 'undefined'),
OpenSeaDragon = annotator.editor.OpenSeaDragon;
return (isOpenSeaDragon && typeof OpenSeaDragon!='undefined' && OpenSeaDragon!==-1);
};
/**
* Detect if the annotation is an image annotation and there's a target, open
* OSD instance.
* @param {Object} an Annotation from the Annotator instance
*/
OpenSeaDragon.prototype.isOpenSeaDragon = function (an){
var annotator = this.annotator;
var rp = an.rangePosition;
// Makes sure OSD exists and that annotation is an image annotation
// with a position in the OSD instance
var isOpenSeaDragon = (typeof annotator.osda != 'undefined');
var isContainer = (typeof an.target!='undefined' && an.target.container==osda.viewer.id );
var isImage = (typeof an.media!='undefined' && an.media=='image');
var isRP = (typeof rp!='undefined');
var isSource = false;
// Double checks that the image being displayed matches the annotations
var source = osda.viewer.source;
var tilesUrl = typeof source.tilesUrl!='undefined'?source.tilesUrl:'';
var functionUrl = typeof source.getTileUrl!='undefined'?source.getTileUrl:'';
var compareUrl = tilesUrl!=''?tilesUrl:('' + functionUrl).replace(/\s+/g, ' ');
if(isContainer) isSource = (an.target.src == compareUrl);
return (isOpenSeaDragon && isContainer && isImage && isRP && isSource);
};
/**
* Deletes the OSD annotation from Annotator and refreshes display to remove element
* @param {Object} an Annotation object from the Annotator instance
*/
OpenSeaDragon.prototype._deleteAnnotation = function(an){
// Remove the annotation of the plugin Store
var annotations = this.annotator.plugins['Store'].annotations;
// Failsafe in case annotation is not immediately removed from annotations list
if (annotations.indexOf(an)>-1)
annotations.splice(annotations.indexOf(an), 1);
// Refresh the annotations in the display
this.annotator.osda.refreshDisplay();
};
//--Listeners
OpenSeaDragon.prototype.initListeners = function (){
var wrapper = $('.annotator-wrapper').parent()[0];
var annotator = $.data(wrapper, 'annotator');
var EditOpenSeaDragonAn = this.EditOpenSeaDragonAn;
var isOpenSeaDragon = this.isOpenSeaDragon;
var self = this;
// local functions
//-- Editor
function annotationEditorHidden(editor) {
if (EditOpenSeaDragonAn()){
annotator.osda._reset();
annotator.osda.refreshDisplay(); // Reload the display of annotations
}
annotator.editor.OpenSeaDragon=-1;
annotator.unsubscribe("annotationEditorHidden", annotationEditorHidden);
};
function annotationEditorShown(editor,annotation) {
annotator.osda.editAnnotation(annotation,editor);
annotator.subscribe("annotationEditorHidden", annotationEditorHidden);
};
//-- Annotations
function annotationDeleted(annotation) {
if (isOpenSeaDragon(annotation))
self._deleteAnnotation(annotation);
};
//-- Viewer
function hideViewer(){
jQuery(annotator.osda.viewer.canvas.parentNode).find('.annotator-hl').map(function() {
return this.style.background = 'rgba(0, 0, 0, 0)';
});
annotator.viewer.unsubscribe("hide", hideViewer);
};
function annotationViewerShown(viewer,annotations) {
var wrapper = jQuery('.annotator-wrapper').offset();
// Fix with positionCanvas
var startPoint = {x: parseFloat(viewer.element[0].style.left),
y: parseFloat(viewer.element[0].style.top)};
var separation = viewer.element.hasClass(viewer.classes.invert.y)?5:-5,
newpos = {
top: (startPoint.y - wrapper.top)+separation,
left: (startPoint.x - wrapper.left)
};
viewer.element.css(newpos);
// Remove the time to wait until disapear, to be more faster that annotator by default
viewer.element.find('.annotator-controls').removeClass(viewer.classes.showControls);
annotator.viewer.subscribe("hide", hideViewer);
};
// subscribe to Annotator
annotator.subscribe("annotationEditorShown", annotationEditorShown)
.subscribe("annotationDeleted", annotationDeleted)
.subscribe("annotationViewerShown", annotationViewerShown);
}
return OpenSeaDragon;
})(Annotator.Plugin);
//----------------PUBLIC OBJECT TO CONTROL THE ANNOTATIONS----------------//
// The name of the plugin that the user will write in the html
OpenSeadragonAnnotation = ("OpenSeadragonAnnotation" in window) ? OpenSeadragonAnnotation : {};
OpenSeadragonAnnotation = function (element, options) {
// local variables
var $ = jQuery;
var options = options || {};
options.optionsOpenSeadragon = options.optionsOpenSeadragon || {};
options.optionsOSDA = options.optionsOSDA || {};
options.optionsAnnotator = options.optionsAnnotator || {};
// if there isn't store optinos it will create a uri and limit variables for the Back-end of Annotations
if (typeof options.optionsAnnotator.store=='undefined')
options.optionsAnnotator.store = {};
var store = options.optionsAnnotator.store;
if (typeof store.annotationData=='undefined')
store.annotationData = {};
if (typeof store.annotationData.uri=='undefined'){
var uri = location.protocol + '//' + location.host + location.pathname;
store.annotationData.store = {uri:uri};
}
if (typeof store.loadFromSearch=='undefined')
store.loadFromSearch={};
if (typeof store.loadFromSearch.uri=='undefined')
store.loadFromSearch.uri = uri;
if (typeof store.loadFromSearch.limit=='undefined')
store.loadFromSearch.limit = 10000;
// global variables
this.currentUser = null;
//-- Init all the classes --/
// Annotator
this.annotator = $(element).annotator(options.optionsAnnotator.annotator).data('annotator');
//-- Activate all the Annotator plugins --//
if (typeof options.optionsAnnotator.auth!='undefined')
this.annotator.addPlugin('Auth', options.optionsAnnotator.auth);
if (typeof options.optionsAnnotator.permissions!='undefined')
this.annotator.addPlugin("Permissions", options.optionsAnnotator.permissions);
if (typeof options.optionsAnnotator.store!='undefined')
this.annotator.addPlugin("Store", options.optionsAnnotator.store);
if (typeof Annotator.Plugin["Geolocation"] === 'function')
this.annotator.addPlugin("Geolocation",options.optionsAnnotator.geolocation);
if (typeof Annotator.Plugin["Share"] === 'function')
this.annotator.addPlugin("Share",options.optionsAnnotator.share);
if (typeof Annotator.Plugin["RichText"] === 'function')
this.annotator.addPlugin("RichText",options.optionsAnnotator.richText);
if (typeof Annotator.Plugin["Reply"] === 'function')
this.annotator.addPlugin("Reply");
if (typeof Annotator.Plugin["OpenSeaDragon"] === 'function')
this.annotator.addPlugin("OpenSeaDragon");
if (typeof Annotator.Plugin["Flagging"] === 'function')
this.annotator.addPlugin("Flagging");
if (typeof Annotator.Plugin["HighlightTags"] === 'function')
this.annotator.addPlugin("HighlightTags", options.optionsAnnotator.highlightTags);
//- OpenSeaDragon
this.viewer = OpenSeadragon(options.optionsOpenSeadragon);
//- OpenSeaDragon Plugins
this.viewer.annotation(options.optionsOSDA);
// Set annotator.editor.OpenSeaDragon by default
this.annotator.editor.OpenSeaDragon=-1;
// We need to make sure that osda is accessible via annotator
this.annotator.osda = this;
function reloadEditor(){
tinymce.EditorManager.execCommand('mceRemoveEditor',true, "annotator-field-0");
tinymce.EditorManager.execCommand('mceAddEditor',true, "annotator-field-0");
// if person hits into/out of fullscreen before closing the editor should close itself
// ideally we would want to keep it open and reposition, this would make a great TODO in the future
annotator.editor.hide();
}
var self = this;
document.addEventListener("fullscreenchange", function () {
reloadEditor();
}, false);
document.addEventListener("mozfullscreenchange", function () {
reloadEditor();
}, false);
document.addEventListener("webkitfullscreenchange", function () {
reloadEditor();
}, false);
document.addEventListener("msfullscreenchange", function () {
reloadEditor();
}, false);
// for some reason the above doesn't work when person hits ESC to exit full screen...
$(document).keyup(function(e) {
// esc key reloads editor as well
if (e.keyCode == 27) {
reloadEditor();
}
});
this.options = options;
return this;
}

View File

@@ -1,22 +0,0 @@
Annotator.Plugin.Auth.prototype.haveValidToken = function() {
return (
this._unsafeToken &&
this._unsafeToken.d.issuedAt &&
this._unsafeToken.d.ttl &&
this._unsafeToken.d.consumerKey &&
this.timeToExpiry() > 0
);
};
Annotator.Plugin.Auth.prototype.timeToExpiry = function() {
var expiry, issue, now, timeToExpiry;
now = new Date().getTime() / 1000;
issue = createDateFromISO8601(this._unsafeToken.d.issuedAt).getTime() / 1000;
expiry = issue + this._unsafeToken.d.ttl;
timeToExpiry = expiry - now;
if (timeToExpiry > 0) {
return timeToExpiry;
} else {
return 0;
}
};

View File

@@ -1,3373 +0,0 @@
// Generated by CoffeeScript 1.6.3
/*
** Annotator v1.2.8-dev-0acc077
** https://github.com/okfn/annotator/
**
** Copyright 2012 Aron Carroll, Rufus Pollock, and Nick Stenning.
** Dual licensed under the MIT and GPLv3 licenses.
** https://github.com/okfn/annotator/blob/master/LICENSE
**
** Built at: 2013-11-25 17:25:07Z
*/
/*
//
*/
// Generated by CoffeeScript 1.6.3
var findChild, getNodeName, getNodePosition, simpleXPathJQuery, simpleXPathPure;
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;
};
/*
//
*/
// Generated by CoffeeScript 1.6.3
var $, Util, gettext_annotator, _ref, _t;
gettext_annotator = function(msgid) {
return msgid;
};
_t = function(msgid) {
return gettext_annotator(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;
};
/*
//
*/
// Generated by CoffeeScript 1.6.3
var fn, functions, _i, _j, _len, _len1,
__slice = [].slice;
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(', ')));
};
}
/*
//
*/
// Generated by CoffeeScript 1.6.3
var Delegator,
__slice = [].slice,
__hasProp = {}.hasOwnProperty;
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, _i, _len, _ref, _results;
_ref = Delegator._parseEvents(this.events);
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
event = _ref[_i];
_results.push(this._addEvent(event.selector, event.event, event.functionName));
}
return _results;
};
Delegator.prototype.removeEvents = function() {
var event, _i, _len, _ref, _results;
_ref = Delegator._parseEvents(this.events);
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
event = _ref[_i];
_results.push(this._removeEvent(event.selector, event.event, event.functionName));
}
return _results;
};
Delegator.prototype._addEvent = function(selector, event, functionName) {
var closure,
_this = this;
closure = function() {
return _this[functionName].apply(_this, arguments);
};
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, _i, _ref;
events = [];
for (sel in eventsObj) {
functionName = eventsObj[sel];
_ref = sel.split(' '), selector = 2 <= _ref.length ? __slice.call(_ref, 0, _i = _ref.length - 1) : (_i = 0, []), event = _ref[_i++];
events.push({
selector: selector.join(' '),
event: event,
functionName: functionName
});
}
return events;
};
Delegator.natives = (function() {
var key, specials, val;
specials = (function() {
var _ref, _results;
_ref = jQuery.event.special;
_results = [];
for (key in _ref) {
if (!__hasProp.call(_ref, key)) continue;
val = _ref[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;
};
/*
//
*/
// Generated by CoffeeScript 1.6.3
var Range,
__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; };
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 _i, _len, _ref, _results;
_ref = xpath.split('/');
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
segment = _ref[_i];
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, _i, _len, _ref;
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();
_ref = $(this.end).parents();
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
parent = _ref[_i];
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, _i, _len;
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 (_i = 0, _len = nodes.length; _i < _len; _i++) {
n = nodes[_i];
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 _i, _len, _ref, _results;
_ref = this.textNodes();
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
_results.push(node.nodeValue);
}
return _results;
}).call(this)).join('');
};
NormalizedRange.prototype.textNodes = function() {
var end, start, textNodes, _ref;
textNodes = Util.getTextNodes($(this.commonAncestor));
_ref = [textNodes.index(this.start), textNodes.index(this.end)], start = _ref[0], end = _ref[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, _i, _j, _len, _len1, _ref, _ref1;
range = {};
_ref = ['start', 'end'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
p = _ref[_i];
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--;
}
_ref1 = Util.getTextNodes($(node));
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
tn = _ref1[_j];
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;
})();
/*
//
*/
// Generated by CoffeeScript 1.6.3
var Annotator, g, _Annotator, _ref,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
_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() {
var _this = this;
this.viewer = new Annotator.Viewer({
readOnly: this.options.readOnly
});
this.viewer.hide().on("edit", this.onEditAnnotation).on("delete", this.onDeleteAnnotation).addField({
load: 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]);
}
}).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') + '\u2026',
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 _i, _len, _ref, _results;
_ref = ['adder', 'outer', 'notice', 'filter'];
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
x = _ref[_i];
_results.push(":not(.annotator-" + x + ")");
}
return _results;
})()).join('');
max = Util.maxZIndex($(document.body).find(sel));
max = Math.max(max, 1000);
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, _ref;
$(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);
_ref = this.plugins;
for (name in _ref) {
plugin = _ref[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, _i, _len;
selection = Util.getGlobal().getSelection();
ranges = [];
rangesToIgnore = [];
if (!selection.isCollapsed) {
ranges = (function() {
var _i, _ref, _results;
_results = [];
for (i = _i = 0, _ref = selection.rangeCount; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
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 (_i = 0, _len = rangesToIgnore.length; _i < _len; _i++) {
r = rangesToIgnore[_i];
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, _i, _j, _len, _len1, _ref;
root = this.wrapper[0];
annotation.ranges || (annotation.ranges = this.selectedRanges);
normedRanges = [];
_ref = annotation.ranges;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
r = _ref[_i];
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;
}
}
}
if (normedRanges.length!=0){
annotation.quote = [];
annotation.ranges = [];
annotation.highlights = [];
for (_j = 0, _len1 = normedRanges.length; _j < _len1; _j++) {
normed = normedRanges[_j];
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, _i, _len, _ref;
if (annotation.highlights != null) {
_ref = annotation.highlights;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
h = _ref[_i];
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,
_this = this;
if (annotations == null) {
annotations = [];
}
loader = function(annList) {
var n, now, _i, _len;
if (annList == null) {
annList = [];
}
now = annList.splice(0, 10);
for (_i = 0, _len = now.length; _i < _len; _i++) {
n = now[_i];
_this.setupAnnotation(n);
}
if (annList.length > 0) {
return setTimeout((function() {
return loader(annList);
}), 10);
} else {
return _this.publish('annotationsLoaded', [clone]);
}
};
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, _i, _len, _ref, _results;
if (cssClass == null) {
cssClass = 'annotator-hl';
}
white = /^\s*$/;
hl = $("<span class='" + cssClass + "'></span>");
_ref = normedRange.textNodes();
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
if (!white.test(node.nodeValue)) {
_results.push($(node).wrapAll(hl).parent().show()[0]);
}
}
return _results;
};
Annotator.prototype.highlightRanges = function(normedRanges, cssClass) {
var highlights, r, _i, _len;
if (cssClass == null) {
cssClass = 'annotator-hl';
}
highlights = [];
for (_i = 0, _len = normedRanges.length; _i < _len; _i++) {
r = normedRanges[_i];
$.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, _i, _len, _ref;
this.mouseIsDown = false;
if (this.ignoreMouseup) {
return;
}
this.selectedRanges = this.getSelectedRanges();
_ref = this.selectedRanges;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
range = _ref[_i];
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,
_this = this;
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() {
cleanup();
$(annotation.highlights).removeClass('annotator-hl-temporary');
return _this.publish('annotationCreated', [annotation]);
};
cancel = function() {
cleanup();
return _this.deleteAnnotation(annotation);
};
cleanup = function() {
_this.unsubscribe('annotationEditorHidden', cancel);
return _this.unsubscribe('annotationEditorSubmit', save);
};
this.subscribe('annotationEditorHidden', cancel);
this.subscribe('annotationEditorSubmit', save);
return this.showEditor(annotation, position);
};
Annotator.prototype.onEditAnnotation = function(annotation) {
var cleanup, offset, update,
_this = this;
offset = this.viewer.element.position();
update = function() {
cleanup();
return _this.updateAnnotation(annotation);
};
cleanup = function() {
_this.unsubscribe('annotationEditorHidden', cleanup);
return _this.unsubscribe('annotationEditorSubmit', update);
};
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 (((_ref = g.document) != null ? _ref.evaluate : void 0) == null) {
$.getScript('//assets.annotateit.org/vendor/xpath.min.js');
}
if (g.getSelection == null) {
$.getScript('//assets.annotateit.org/vendor/ierange.min.js');
}
if (g.JSON == null) {
$.getScript('//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);
var temp = 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);
}
});
return temp;
};
this.Annotator = Annotator;
/*
//
*/
// Generated by CoffeeScript 1.6.3
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
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);
/*
//
*/
// Generated by CoffeeScript 1.6.3
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
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, _i, _len, _ref;
this.annotation = annotation;
this.publish('load', [this.annotation]);
_ref = this.fields;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
field = _ref[_i];
field.load(field.element, this.annotation);
}
return this.show();
};
Editor.prototype.submit = function(event) {
var field, _i, _len, _ref;
Annotator.Util.preventEventDefault(event);
_ref = this.fields;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
field = _ref[_i];
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('.annotator-listing');
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 = this;
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(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;
}, 1000 / 60);
}
};
resize.bind('mousedown', onMousedown);
return controls.bind('mousedown', onMousedown);
};
return Editor;
})(Annotator.Widget);
/*
//
*/
// Generated by CoffeeScript 1.6.3
var LinkParser,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
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,
_this = this;
Annotator.Util.preventEventDefault(event);
controls = this.element.find('.annotator-controls').addClass(this.classes.showControls);
setTimeout((function() {
return controls.removeClass(_this.classes.showControls);
}), 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, _i, _j, _len, _len1, _ref, _ref1;
this.annotations = annotations || [];
list = this.element.find('ul:first').empty();
_ref = this.annotations;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
annotation = _ref[_i];
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');
}
};
}
_ref1 = this.fields;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
field = _ref1[_j];
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, _i, _len, _ref, _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;
})();
_ref = this.data;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
d = _ref[_i];
match = keys.reduce((function(m, k) {
return m && (d[k] === cond[k]);
}), true);
if (match) {
_results.push(d);
} else {
continue;
}
}
return _results;
};
return LinkParser;
})();
/*
//
*/
// Generated by CoffeeScript 1.6.3
var Annotator,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
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, 5000);
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;
});
/*
//
*/
// Generated by CoffeeScript 1.6.3
var _ref,
__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; };
Annotator.Plugin.Unsupported = (function(_super) {
__extends(Unsupported, _super);
function Unsupported() {
_ref = Unsupported.__super__.constructor.apply(this, arguments);
return _ref;
}
Unsupported.prototype.options = {
message: Annotator._t("Sorry your current browser does not support the Annotator")
};
Unsupported.prototype.pluginInit = function() {
var _this = this;
if (!Annotator.supported()) {
return $(function() {
Annotator.showNotification(_this.options.message);
if ((window.XMLHttpRequest === void 0) && (ActiveXObject !== void 0)) {
return $('html').addClass('ie6');
}
});
}
};
return Unsupported;
})(Annotator.Plugin);
/*
//
*/
// Generated by CoffeeScript 1.6.3
var base64Decode, base64UrlDecode, createDateFromISO8601, parseToken,
__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; };
createDateFromISO8601 = function(string) {
var d, date, offset, regexp, time, _ref;
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]) * 1000);
}
if (d[14]) {
offset = (Number(d[16]) * 60) + Number(d[17]);
offset *= (_ref = d[15] === '-') != null ? _ref : {
1: -1
};
}
offset -= date.getTimezoneOffset();
time = Number(date) + (offset * 60 * 1000);
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 & 0xff;
o2 = bits >> 8 & 0xff;
o3 = bits & 0xff;
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, _i, _ref;
m = data.length % 4;
if (m !== 0) {
for (i = _i = 0, _ref = 4 - m; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
data += '=';
}
}
data = data.replace(/-/g, '+');
data = data.replace(/_/g, '/');
return base64Decode(data);
};
parseToken = function(token) {
var head, payload, sig, _ref;
_ref = token.split('.'), head = _ref[0], payload = _ref[1], sig = _ref[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() {
var _this = this;
this.requestInProgress = true;
return $.ajax({
url: this.options.tokenUrl,
dataType: 'text',
xhrFields: {
withCredentials: true
}
}).done(function(data, status, xhr) {
return _this.setToken(data);
}).fail(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);
}).always(function() {
return _this.requestInProgress = false;
});
};
Auth.prototype.setToken = function(token) {
var _results,
_this = this;
this.token = token;
this._unsafeToken = parseToken(token);
if (this.haveValidToken()) {
if (this.options.autoFetch) {
this.refreshTimeout = setTimeout((function() {
return _this.requestToken();
}), (this.timeToExpiry() - 2) * 1000);
}
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() {
return _this.requestToken();
}), 10 * 1000);
}
}
};
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() / 1000;
issue = createDateFromISO8601(this._unsafeToken.issuedAt).getTime() / 1000;
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);
/*
//
*/
// Generated by CoffeeScript 1.6.3
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__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; };
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) {
var _this = this;
if (__indexOf.call(this.annotations, annotation) < 0) {
this.registerAnnotation(annotation);
return this._apiRequest('create', annotation, function(data) {
if (data.id == null) {
console.warn(Annotator._t("Warning: No ID returned from server for annotation "), annotation);
}
return _this.updateAnnotation(annotation, data);
});
} else {
return this.updateAnnotation(annotation, {});
}
};
Store.prototype.annotationUpdated = function(annotation) {
var _this = this;
if (__indexOf.call(this.annotations, annotation) >= 0) {
return this._apiRequest('update', annotation, (function(data) {
return _this.updateAnnotation(annotation, data);
}));
}
};
Store.prototype.annotationDeleted = function(annotation) {
var _this = this;
if (__indexOf.call(this.annotations, annotation) >= 0) {
return this._apiRequest('destroy', annotation, (function() {
return _this.unregisterAnnotation(annotation);
}));
}
};
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, _i, _j, _len, _len1, _ref;
if (data == null) {
data = [];
}
annotationMap = {};
_ref = this.annotations;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
a = _ref[_i];
annotationMap[a.id] = a;
}
newData = [];
for (_j = 0, _len1 = data.length; _j < _len1; _j++) {
a = data[_j];
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, _i, _len, _ref, _results;
_ref = this.annotations;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
ann = _ref[_i];
_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, our server seems to be down. We could not ") + action + Annotator._t(" this annotation");
if (xhr._action === 'search') {
message = Annotator._t("Sorry, the Annotations service is down. Contact your instructor and try again later.");
} else if (xhr._action === 'read' && !xhr._id) {
message = Annotator._t("Sorry, our server seems to be down. We could not ") + action + Annotator._t(" the annotation(s).");
}
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 database.");
break;
case 500:
message = Annotator._t("Sorry, our server is down. Contact your instructor and try again later.");
}
Annotator.showNotification(message, Annotator.Notification.ERROR);
return console.error(Annotator._t("API request failed:") + (" '" + xhr.status + "'"));
};
return Store;
})(Annotator.Plugin);
/*
//
*/
// Generated by CoffeeScript 1.6.3
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
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, _i, _len;
if (annotation.permissions) {
tokens = annotation.permissions[action] || [];
if (tokens.length === 0) {
return true;
}
for (_i = 0, _len = tokens.length; _i < _len; _i++) {
token = tokens[_i];
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,
_this = this;
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(input, user) {
var keyword, _i, _len, _ref;
user = _this.options.userString(user);
if (!(input && user)) {
return false;
}
_ref = input.split(/\s*/);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
keyword = _ref[_i];
if (user.indexOf(keyword) === -1) {
return false;
}
}
return true;
}
});
}
};
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);
/*
//
*/
// Generated by CoffeeScript 1.6.3
var _ref,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__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; };
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);
_ref = AnnotateItPermissions.__super__.constructor.apply(this, arguments);
return _ref;
}
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, _ref1, _ref2, _ref3, _ref4;
permissions = annotation.permissions || {};
action_field = permissions[action] || [];
if (_ref1 = this.groups.world, __indexOf.call(action_field, _ref1) >= 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 (_ref2 = this.groups.authenticated, __indexOf.call(action_field, _ref2) >= 0) {
return true;
} else if (user.consumerKey === annotation.consumer && (_ref3 = this.groups.consumer, __indexOf.call(action_field, _ref3) >= 0)) {
return true;
} else if (user.consumerKey === annotation.consumer && (_ref4 = user.userId, __indexOf.call(action_field, _ref4) >= 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);
/*
//
*/
// Generated by CoffeeScript 1.6.3
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
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, _i, _len, _ref;
if (!(input && property)) {
return false;
}
_ref = input.split(/\s+/);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
keyword = _ref[_i];
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, _i, _len, _ref;
_ref = this.options.filters;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
filter = _ref[_i];
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, _i, _len;
events = ['annotationsLoaded', 'annotationCreated', 'annotationUpdated', 'annotationDeleted'];
for (_i = 0, _len = events.length; _i < _len; _i++) {
event = events[_i];
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 _i, _len, _ref, _results;
_ref = this.filters;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
f = _ref[_i];
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 + '\u2026'
});
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, _i, _len, _ref;
filter.annotations = [];
this.updateHighlights();
this.resetHighlights();
input = $.trim(filter.element.find('input').val());
if (input) {
annotations = this.highlights.map(function() {
return $(this).data('annotation');
});
_ref = $.makeArray(annotations);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
annotation = _ref[_i];
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, _i, _len, _ref;
activeFilters = $.grep(this.filters, function(filter) {
return !!filter.annotations.length;
});
filtered = ((_ref = activeFilters[0]) != null ? _ref.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 = _i = 0, _len = filtered.length; _i < _len; index = ++_i) {
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);
/*
//
*/
// Generated by CoffeeScript 1.6.3
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
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);
/*
//
*/
// Generated by CoffeeScript 1.6.3
var _ref,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
Annotator.Plugin.Tags = (function(_super) {
__extends(Tags, _super);
function Tags() {
this.setAnnotationTags = __bind(this.setAnnotationTags, this);
this.updateField = __bind(this.updateField, this);
_ref = Tags.__super__.constructor.apply(this, arguments);
return _ref;
}
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') + '\u2026',
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, _i, _j, _len, _len1;
if (tags == null) {
tags = [];
}
matches = 0;
keywords = [];
if (input) {
keywords = input.split(/\s+/g);
for (_i = 0, _len = keywords.length; _i < _len; _i++) {
keyword = keywords[_i];
if (tags.length) {
for (_j = 0, _len1 = tags.length; _j < _len1; _j++) {
tag = tags[_j];
if (tag.indexOf(keyword) !== -1) {
matches += 1;
}
}
}
}
}
return matches === keywords.length;
};
/*
//
*/
// Generated by CoffeeScript 1.6.3
var __hasProp = {}.hasOwnProperty,
__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; };
Annotator.prototype.setupPlugins = function(config, options) {
var name, opts, pluginConfig, plugins, uri, win, _i, _len, _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 (_i = 0, _len = plugins.length; _i < _len; _i++) {
name = plugins[_i];
if (!(name in pluginConfig) || pluginConfig[name]) {
_results.push(this.addPlugin(name, pluginConfig[name]));
} else {
_results.push(void 0);
}
}
return _results;
};
/*
//
*/

View File

@@ -1,538 +0,0 @@
#mainCatch body,
#mainCatch div,
#mainCatch p,
#mainCatch canvas,
#mainCatch h1,
#mainCatch h2 {
margin: 0;
padding: 0;
}
#mainCatch h1{
font-size: 1.6em;
}
#mainCatch body {
font-family: Helvetica, Arial, sans-serif;
}
#mainCatch div {
overflow: hidden;
}
#mainCatch header {
margin: 30px auto;
text-align: center;
width: 100%;
}
#mainCatch #main {
min-width: 640px;
padding-bottom: 100px;
}
/* GRID FORMATTING */
#mainCatch .field {
padding: 0 10px;
float: left;
text-overflow: ellipsis;
white-space: nowrap;
}
/* ANNOTATION LIST */
#mainCatch.annotationListContainer {
width: 100%;
margin: 0 auto;
}
#mainCatch .annotationList {
width: 100%;
font-size:0.8em;
border: 2px solid #dddddd;
padding: 0;
}
#mainCatch .annotationList .ui-tabs-nav{
background: transparent;
border-width: 0px 0px 1px 0px;
-moz-border-radius: 0px;
-webkit-border-radius: 0px;
border-radius: 0px;
margin: 0;
}
#mainCatch .annotationList li {
list-style: none;
position: relative;
top: 0;
margin: 1px .2em 0 0;
border-bottom-width: 0;
white-space: nowrap;
float: left;
padding: .5em 1em;
text-decoration: none;
}
#mainCatch .annotationList .ui-state-default{
border: 1px solid #d3d3d3;
background: #fff 50% 50% repeat-x;
font-weight: normal;
color: #555555;
cursor:pointer;
}
#mainCatch .annotationList .ui-state-default:hover{
border: 1px solid #999999;
background: #fff 50% 50% repeat-x;
font-weight: normal;
color: #212121;
}
#mainCatch .annotationList .ui-state-default.active{
border: 1px solid #aaaaaa;
background: #dadada 50% 50% repeat-x;
font-weight: normal;
color: #212121;
cursor:default;
}
#mainCatch .annotationList .header {
background-color:whitesmoke;
font-weight: bold;
border-bottom: 2px solid #dddddd;
clear:left;
border-top:2px solid #dadada;
}
/* ANNOTATION ROW */
#mainCatch .annotationRow {
width: 100%;
padding-top:12px;
height: 30px;
}
#mainCatch .annotationRow.item {
cursor: pointer;
}
#mainCatch .expandableIcon img, .closeDetailIcon img {
max-width: none !important;
height: 16px;
}
#mainCatch .expandableIcon .visible {
display: block;
}
#mainCatch .expandableIcon .hidden {
display: none;
}
#mainCatch .annotationItem.odd .annotationRow {
/* background-color: #eaffea; */
}
#mainCatch .annotationItem.even .annotationRow {
/* background-color: #f4fff4; */
}
#mainCatch .annotationRow .expandableIcon {
width: 4%;
}
#mainCatch .annotationRow .annotatedBy {
width: 12%;
}
#mainCatch .annotationRow .body {
width: 32%;
}
#mainCatch .annotationRow .start {
width: 8%;
}
#mainCatch .annotationRow .end {
width: 8%;
}
#mainCatch .annotationRow .annotatedAt {
width: 25%;
}
#mainCatch .annotationRow .totalreplies {
width: 9%;
}
#mainCatch .annotationItem.open .annotationRow {
display: none;
}
/* ANNOTATION DETAIL */
#mainCatch .annotationItem.closed .annotationDetail {
display: none;
}
#mainCatch .annotationDetail {
border-top:1px solid #cccccc;
border-bottom:1px solid #cccccc;
padding-left:30px;
padding-bottom:15px;
}
#mainCatch .annotationDetail .detailHeader {
font-style: italic;
margin-top:10px;
cursor: pointer;
}
#mainCatch .annotationDetail .quote {
font-style:italic;
color: #666666;
background-color: #f7f579;
padding: 7px 10px 7px 10px;
margin: 10px 20px 5px 0px;
font-size: 16px;
cursor: pointer;
}
#mainCatch .annotationDetail .quote .quoteText{
padding: 7px;
display: inline;
}
#mainCatch .annotationDetail .quote .quoteItem{
font-size: 30px;
display: inline;
}
#mainCatch .annotationDetail .quote p, #mainCatch .annotationDetail .body p {
padding:5px 0;
}
/* PLAY MEDIA BUTTON STYLING EXTERNALLY GENERATED */
#mainCatch .playMediaButton {
width:18em;
font-weight: bold;
text-align: center;
margin-top: 15px;
}
#mainCatch .zoomToImageBounds {
width: 20em;
text-align:center;
margin-top: 15px;
margin-bottom: 5px;
}
#mainCatch .playMediaButton, #mainCatch .zoomToImageBounds {
border-top: 2px solid #d3bd89;
border-bottom: 2px solid #b3ad69;
border-right: 2px solid #b3ad69;
border-left: 2px solid #b3ad69;
background: #f7f579;
background: -webkit-gradient(linear, left top, left bottom, from(#f7e734), to(#f7f579));
background: -webkit-linear-gradient(top, #f7e734, #f7f579);
background: -moz-linear-gradient(top, #f7e734, #f7f579);
background: -ms-linear-gradient(top, #f7e734, #f7f579);
background: -o-linear-gradient(top, #f7e734, #f7f579);
padding: 10px 20px;
-webkit-border-radius: 24px;
-moz-border-radius: 24px;
border-radius: 24px;
color: #000000;
}
#mainCatch .playMediaButton:hover, #mainCatch .zoomToImageBounds:hover {
border-top: 2px solid #d3bd89;
border-bottom: 2px solid #b3ad69;
border-right: 2px solid #b3ad69;
border-left: 2px solid #b3ad69;
background: #f5c105;
color: #080708;
}
#mainCatch .playMediaButton:active, #mainCatch .zoomToImageBounds:active {
border-top: 2px solid #d3bd89;
border-bottom: 2px solid #b3ad69;
border-right: 2px solid #b3ad69;
border-left: 2px solid #b3ad69;
background: #eb7f0c;
}
/* TAGS */
#mainCatch .tags {
margin-bottom: 30px;
}
/* TAG BUTTON */
#mainCatch .tag {
max-width:200px;
font-weight: bold;
text-align: center;
float: left;
margin-right: 10px;
}
#mainCatch .tag {
border-top: 2px solid #999999;
border-bottom: 2px solid #999999;
border-right: 2px solid #999999;
border-left: 2px solid #999999;
background: #dddddd;
background: -webkit-gradient(linear, left top, left bottom, from(#eeeeee), to(#dddddd));
background: -webkit-linear-gradient(top, #eeeeee, #dddddd);
background: -moz-linear-gradient(top, #eeeeee, #dddddd);
background: -ms-linear-gradient(top, #eeeeee, #dddddd);
background: -o-linear-gradient(top, #eeeeee, #dddddd);
padding: 5px 10px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
color: #000000;
}
#mainCatch .tag:hover {
background: #cccccc;
}
#mainCatch .tag:active {
background: #bbbbbb;
}
/* VIDEO ANNOTATION DETAIL */
#mainCatch .geolocationIcon img {
height: 28px;
}
#mainCatch .videoAnnotationDetail .body {
padding: 5px 0;
}
/*PublicPrivate Notes in My notes */
#mainCatch .annotationListButtons span{
display:none;
}
#mainCatch .annotationListButtons .PublicPrivate{
cursor: pointer;
}
#mainCatch .annotationListButtons .PublicPrivate.separator,
#mainCatch .annotationListButtons .PublicPrivate.myNotes{
position:relative;
float:left;
}
#mainCatch .annotationListButtons .PublicPrivate.active *{
color:black;
text-decoration: underline;
}
/* My notes buttons */
#mainCatch .annotationListButtons .moreButtonCatch{
-moz-box-shadow:inset 0px 1px 0px 0px #ffffff;
-webkit-box-shadow:inset 0px 1px 0px 0px #ffffff;
box-shadow:inset 0px 1px 0px 0px #ffffff;
background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #ffffff), color-stop(1, #a6a3a3));
background:-moz-linear-gradient(top, #ffffff 5%, #a6a3a3 100%);
background:-webkit-linear-gradient(top, #ffffff 5%, #a6a3a3 100%);
background:-o-linear-gradient(top, #ffffff 5%, #a6a3a3 100%);
background:-ms-linear-gradient(top, #ffffff 5%, #a6a3a3 100%);
background:linear-gradient(to bottom, #ffffff 5%, #a6a3a3 100%);
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#a6a3a3',GradientType=0);
background-color:#ffffff;
-moz-border-radius:6px;
-webkit-border-radius:6px;
border-radius:6px;
border:1px solid #c2c2c2;
display:inline-block;
color:#302f2f;
font-family:arial;
font-size:15px;
font-weight:bold;
padding:6px 24px;
text-decoration:none;
text-shadow:0px 1px 0px #ffffff;
margin: 0px 5px 10px 5px;
cursor:pointer;
}
#mainCatch .annotationListButtons .PublicPrivate{
-moz-box-shadow:inset 0px 1px 0px 0px #ffffff;
-webkit-box-shadow:inset 0px 1px 0px 0px #ffffff;
box-shadow:inset 0px 1px 0px 0px #ffffff;
background-color:#fff;
border:1px solid #c2c2c2;
display:inline-block;
color:#302f2f;
font-family:arial;
font-size:14px;
font-weight:bold;
padding:6px 24px;
text-decoration:none;
margin: 0px 0px 10px 0px;
cursor:pointer;
width:115px;
text-align:center;
}
#mainCatch .annotationListButtons .PublicPrivate.myNotes{
-moz-border-top-left-radius:6px;
-webkit-border-top-left-radius:6px;
border-radius-top-left:6px;
-moz-border-bottom-left-radius:6px;
-webkit-border-bottom-left-radius:6px;
border-radius-bottom-left:6px;
}
#mainCatch .annotationListButtons .PublicPrivate.public{
-moz-border-top-right-radius:6px;
-webkit-border-top-right-radius:6px;
border-radius-top-right:6px;
-moz-border-bottom-right-radius:6px;
-webkit-border-bottom-right-radius:6px;
border-radius-bottom-right:6px;
}
#mainCatch .annotationListButtons .PublicPrivate.active:hover,
#mainCatch .annotationListButtons .PublicPrivate.active{
color:#302f2f;
background-color:#dadada;
cursor:default;
}
#mainCatch .annotationListButtons .moreButtonCatch:hover {
background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #a6a3a3), color-stop(1, #ffffff));
background:-moz-linear-gradient(top, #a6a3a3 5%, #ffffff 100%);
background:-webkit-linear-gradient(top, #a6a3a3 5%, #ffffff 100%);
background:-o-linear-gradient(top, #a6a3a3 5%, #ffffff 100%);
background:-ms-linear-gradient(top, #a6a3a3 5%, #ffffff 100%);
background:linear-gradient(to bottom, #a6a3a3 5%, #ffffff 100%);
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#a6a3a3', endColorstr='#ffffff',GradientType=0);
background-color:#a6a3a3;
}
#mainCatch .annotationListButtons .PublicPrivate:hover{
background-color:#868383;
}
#mainCatch .annotationListButtons .publicPrivate:active,
#mainCatch .annotationListButtons .moreButtonCatch:active {
position:relative;
top:1px;
}
/* More Button */
#mainCatch .annotationListButtons .moreButtonCatch{
width: 100%;
margin: 0;
text-align: center;
}
/* control Panel */
#mainCatch .controlPanel .groups_button,
#mainCatch .controlPanel .share-container-annotator{
position: relative;
float:left;
cursor:pointer;
}
#mainCatch .controlPanel .share-container-annotator{
min-width: 0;
padding-left: 4px;
top: -3px;
}
#mainCatch .controlReplies div{
position: relative;
float: left;
text-decoration: underline;
margin: 5px;
cursor: pointer;
}
#mainCatch .searchbox input{
margin: 0;
padding: 0;
width: 50%;
margin-left: 10px;
display: inline;
float: left;
}
#mainCatch .searchbox .dropdown-list{
width: 18%;
float: left;
margin-top: 5px;
}
#mainCatch .searchbox .search-icon{
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAA3NCSVQICAjb4U/gAAAApVBMVEVmZmaPj4/f399mZmbBwcF8fHykpKTX19dycnLl5eWDg4O5ubmfn5/MzMyHh4fp6em1tbVsbGx5eXmZmZnu7u7h4eGLi4uZmZl+fn7ExMTd3d1wcHDx8fHR0dHj4+NqamqBgYGFhYV0dHS7u7va2tp6enrn5+eoqKhubm6NjY2hoaGJiYnr6+vv7+/Hx8d2dna3t7fDw8PPz8+9vb2RkZGnp6f39/dv4zATAAAAN3RSTlP///////////////////////////////////////////////////////////////////////8AEFmdiwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAB50RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNS4xqx9I6wAAABZ0RVh0Q3JlYXRpb24gVGltZQAxMi8xNi8xM93x4EAAAAF1SURBVDiNjdThbsIgEADgk8jWYtdZsaZ22pqqmW7GGZPd+z/aDnDWApXyq9AvcAcHgAMbtJ/xRKapnMQBuJ2BabU4P4GlgLbVo6oPvnENmqJoavXVXP2w/KCf2ctKR5pk1JnlPrhK6dei/B/aFdQ9+uCEluPzduxEAddjD9wARJ1N2R0AhAsZTfjZHU1oyncHTikRazSnKMcOlAA/dui0DdKBFHphwz1tgw9yG858cERJ25DSThx4cVNUySwdWNH2/HZHpXd7kCoie30cvGbeDcctLfT9MEFMh52tPVCdIezvRbGOqDuy0zNlpurlkOjzriRlDNy5EKZw140u7YgXkSlyzvwQ40UNnba3b8P9co3FjdbpRcfMeiDi/Px1PCbLExUeHTVs4j740ColozwMkanVBQtDjCMrzj6IuXoSeBmGJqN29X6ITD0fDQtD8yClLAyRNe2cTyEy9dgULAzNnFoGIDJVgWIA1HIQRCaEHARvbTD8A+tpEWRTORVbAAAAAElFTkSuQmCC');
width: 16px;
background-size: cover;
height: 16px;
background-repeat: no-repeat;
position: relative;
float: left;
margin-left: 10px;
margin-top: 10px;
cursor:pointer;
}
#mainCatch .searchbox .clear-search-icon{
font-size: 12px;
text-decoration: underline;
float: right;
margin-top: 10px;
padding-right: 3px;
cursor:pointer;
}
#mainCatch .searchbox .search-icon:hover{
opacity:0.5;
box-shadow: 2px 4px 5px #888888;
}
#mainCatch .selectors{
width:45%;
position:relative;
float:left;
}
#mainCatch .searchbox{
width:52%;
position:relative;
float:right;
}
#mainCatch .searchbox .searchinst{
float:left;
position:relative;
padding-right:5px;
margin-top:8px;
font-size:14px;
}
#mainCatch .replies .replyItem .deleteReply{
text-decoration: underline;
cursor: pointer;
}
#mainCatch div.annotations-loading-gif{
width:100%;
text-align:center;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 599 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 504 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 B

View File

@@ -1,1249 +0,0 @@
/*
Grid Annotation Plugin v1.0
Copyright (C) 2014 Daniel Cebrian Robles and Luis Duarte
License: https://github.com/danielcebrian/share-annotator/blob/master/License.rst
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// The name of the plugin that the user will write in the html
window.CatchAnnotation = ("CatchAnnotation" in window) ? CatchAnnotation : {};
window.CatchSources = ("CatchSources" in window) ? CatchSources : {};
//
// HTML TEMPLATES
//
CatchSources.HTMLTEMPLATES = function(root){
var root = root || '';
return {
// Main
annotationList:
'<div class="annotationListButtons">'+
'{{{ PublicPrivate }}}'+
'</div>'+
'<div class="annotationList">'+
'{{{ MediaSelector }}}'+
'<div class="header">'+
'<div class="annotationRow">'+
'<div class="expandableIcon field">'+
'&nbsp <!-- TODO: better way to ensure width upon hide -->'+
'</div>'+
'<div class="annotatedBy field">'+
gettext('User')+
'</div>'+
'<div class="body field">'+
gettext('Annotation')+
'</div>'+
'{{#if videoFormat}}'+
'<div class="start field">'+
gettext('Start')+
'</div>'+
'<div class="end field">'+
gettext('End')+
'</div>'+
'{{/if}}'+
'<div class="totalreplies field">'+
gettext('#Replies')+
'</div>'+
'<div class="annotatedAt field">'+
gettext('Date posted')+
'</div>'+
'</div>'+
'</div>'+
'{{#each annotationItems}}'+
'{{{ this }}}'+
'{{/each}}'+
'</div>'+
'<div class="annotationListButtons">'+
'<div class="moreButtonCatch">'+gettext('More')+'</div>'+
'</div>',
// Main->PublicPrivateInstructor
annotationPublicPrivateInstructor:
'<div class="selectors"><div class="PublicPrivate myNotes active">'+gettext('My Notes')+'<span class="action">myNotes</span></div>'+
'<div class="PublicPrivate instructor"> '+gettext('Instructor')+'<span class="action">instructor</span></div>'+
'<div class="PublicPrivate public"> '+gettext('Public')+'<span class="action">public</span></div></div>'+
'<div class="searchbox"><div class="searchinst">'+gettext('Search')+'</div><select class="dropdown-list">'+
'<option>'+gettext('Users')+'</option>'+
'<option>'+gettext('Tags')+'</option>'+
'<option>'+gettext('Annotation Text')+'</option>'+
'</select><input type="text" name="search"/><div class="search-icon" alt="Run search."></div><div class="clear-search-icon" alt="Clear search.">'+gettext('Clear')+'</div></div>',
// Main->PublicPrivate
annotationPublicPrivate:
'<div class="selectors"><div class="PublicPrivate myNotes active">'+gettext('My Notes')+'<span class="action">myNotes</span></div>'+
'<div class="PublicPrivate public"> '+gettext('Public')+'<span class="action">public</span></div></div>'+
'<div class="searchbox"><div class="searchinst">'+gettext('Search')+'</div><select class="dropdown-list">'+
'<option>'+gettext('Users')+'</option>'+
'<option>'+gettext('Tags')+'</option>'+
'<option>'+gettext('Annotation Text')+'</option>'+
'</select><input type="text" name="search"/><div class="search-icon" alt="Run search."></div><div class="clear-search-icon" alt="Clear search.">'+gettext('Clear')+'</div></div>',
// Main->MediaSelector
annotationMediaSelector:
'<ul class="ui-tabs-nav">'+
'<li class="ui-state-default" media="text">'+
gettext('Text')+
'</li>'+
'<li class="ui-state-default" media="video">'+
gettext('Video')+
'</li>'+
'<li class="ui-state-default" media="image">'+
gettext('Image')+
'</li>'+
'</ul>',
// Main->ContainerRow
annotationItem:
'<div class="annotationItem {{ evenOrOdd }} {{ openOrClosed }}" annotationId="{{ id }}">'+
'{{{ annotationRow }}}'+
'{{{ annotationDetail }}}'+
'</div>',
// Main->ContainerRow->Reply
annotationReply:
'{{#if annotations}}'+
'{{#each annotations}}'+
'<blockquote class="replyItem" annotationId="{{this.id}}" style="font-size:90%">'+
'<p>'+
'On {{ this.updated }} <!--<a href="index.php?r=user/user/view&id={{{this.user.id}}}">-->{{{ this.user.name }}}<!--</a>-->{{#if this.geolocation}}, wrote from {{/if}}'+
'{{#if geolocation}}'+
'<span class="geolocationIcon">'+
'<img src="'+root+'geolocation_icon.png"width="25" height="25" alt="Location Map" title="Show Location Map" data-dropdown="myLocationMap"/>'+
'<span class="idAnnotation" style="display:none">{{{ this.id }}}</span>'+
'<span class="latitude" style="display:none">{{{ this.geolocation.latitude }}}</span>'+
'<span class="longitude" style="display:none">{{{ this.geolocation.longitude }}}</span>'+
'</span>'+
'<div id="myLocationMap" data-dropdown-content class="f-dropdown content">'+
'<div class="map"></div>'+
'</div>'+
'{{/if}}'+
'<div class="deleteReply">'+gettext('Delete')+'</div>'+
'</p>'+
'<p>'+
'{{#if this.text}}'+
'{{{this.text}}}'+
'{{else}}'+
'-'+
'{{/if}}'+
'</p>'+
'</blockquote>'+
'{{/each}}'+
'{{/if}}',
// Main->ContainerRow->Row
annotationRow:
'<div class="annotationRow item">'+
'<div class="expandableIcon field">'+
'<img src="'+root+'expandableIcon.png" alt="View Details" />'+
'&nbsp'+
'</div>'+
'<div class="annotatedBy field">'+
'{{ user.name }}'+
'</div>'+
'<div class="body field">'+
'{{#if plainText}}'+
'{{deparagraph plainText}}'+
'{{else}}'+
'-'+
'{{/if}}'+
'</div>'+
'<div class="start field">'+
'{{ rangeTime.start }}'+
'</div>'+
'<div class="end field">'+
'{{ rangeTime.end }}'+
'</div>'+
'<div class="totalreplies field">'+
'{{ totalComments }}'+
'</div>'+
'<div class="annotatedAt field">'+
'{{ updated }}'+
'</div>'+
'</div>',
// Main->ContainerRow->DetailRow
annotationDetail:
'{{#if mediatypeforgrid.text}}'+
'<div class="annotationDetail">'+
'{{/if}}'+
'{{#if mediatypeforgrid.video}}'+
'<div class="annotationDetail videoAnnotationDetail">'+
'{{/if}}'+
'{{#if mediatypeforgrid.image}}'+
'<div class="annotationDetail imageAnnotationDetail">'+
'{{/if}}'+
'<div class="detailHeader">'+
'<span class="closeDetailIcon">'+
'<img src="'+root+'closeIcon.png" alt="Hide Details" />'+
'</span>'+
'On {{ updated }} <!--<a href="index.php?r=user/user/view&id={{{user.id}}}">-->{{{ user.name }}}<!--</a>-->{{#if geolocation}}, wrote from {{/if}}'+
'{{#if geolocation}}'+
'<span class="geolocationIcon">'+
'<img src="'+root+'geolocation_icon.png"width="25" height="25" alt="Location Map" title="Show Location Map" data-dropdown="myLocationMap"/>'+
'<span class="idAnnotation" style="display:none">{{{ id }}}</span>'+
'<span class="latitude" style="display:none">{{{ geolocation.latitude }}}</span>'+
'<span class="longitude" style="display:none">{{{ geolocation.longitude }}}</span>'+
'</span>'+
'<div id="myLocationMap" data-dropdown-content class="f-dropdown content">'+
'<div class="map"></div>'+
'</div>'+
'{{/if}}'+
'</div>'+
'{{#if mediatypeforgrid.text}}'+
'<div class="quote">'+
'<div style="text-align: center">'+
'<div class="quoteItem">“</div><div class="quoteText">{{{ quote }}}</div><div class="quoteItem">”</div></div>'+
'<span class="idAnnotation" style="display:none">{{{ id }}}</span>'+
'<span class="uri" style="display:none">{{{uri}}}</span>'+
'</div>'+
'{{/if}}'+
'{{#if mediatypeforgrid.video}}'+
'<div class="playMediaButton">'+
'Play segment {{{ rangeTime.start }}} - {{{ rangeTime.end }}}'+
'<span class="idAnnotation" style="display:none">{{{ id }}}</span>'+
'<span class="uri" style="display:none">{{{uri}}}</span>'+
'<span class="container" style="display:none">{{{target.container}}}</span>'+
'</div>'+
'{{/if}}'+
'{{#if mediatypeforgrid.image}}'+
'<div class="zoomToImageBounds">'+
'<img src="{{{ thumbnailLink }}}">'+
'<span class="idAnnotation" style="display:none">{{{ id }}}</span>'+
'<span class="uri" style="display:none">{{{uri}}}</span>'+
'</div>'+
'{{/if}}'+
'<div class="body">'+
'{{{ text }}}'+
'</div>'+
'<div class="controlReplies">'+
'<div class="newReply" style="text-decoration:underline">'+gettext('Reply')+'</div>&nbsp;'+
'<div class="hideReplies" style="text-decoration:underline;display:{{#if hasReplies}}block{{else}}none{{/if}}">Show Replies</div>&nbsp;'+
'{{#if authToEditButton}}'+
'<div class="editAnnotation" style="text-decoration:underline">'+gettext('Edit')+'</div>'+
'{{/if}}'+
'{{#if authToDeleteButton}}'+
'<div class="deleteAnnotation" style="text-decoration:underline">'+gettext('Delete')+'</div>'+
'{{/if}}'+
'</div>'+
'<div class="replies"></div>'+
'{{#if tags}}'+
'<div class="tags">'+
'<h3>'+gettext('Tags:')+'</h3>'+
'{{#each tags}}'+
'<div class="tag">'+
'{{this}}'+
'</div>'+
'{{/each}}'+
'</div>'+
'{{/if}}'+
'<div class="controlPanel">'+
'</div>'+
'</div>',
};
};
CatchAnnotation = function (element, options) {
// local variables
var $ = jQuery,
options = options || {};
// Options
var defaultOptions = {
media: 'text',
userId: '', // this is an integer and its value is the userId to see user annotations
externalLink: false, // This is true if you want to open the link in a new URL. However, it is false if you want to open the url in the same page
showMediaSelector: true, // whether show the selector of Media Annotations or not
showPublicPrivate: true, // Whether show Public or Private Annotation Selector
pagination: 50, // Number of Annotations per load in the pagination
flags:false // This checks to see if user is staff and has access to see flags
};
this.options = $.extend( true, defaultOptions, options );
// element
this.element = element;
// clean boolean
this.clean = false;
// Reset element an create a new element div
element.html('<div id="mainCatch" class="annotationListContainer"></div>');
this.current_tab = this.options.default_tab;
// INIT
var self = this;
$( document ).ready(function() {
self.init();
self.refreshCatch(true);
var moreBut = self.element.find('.annotationListButtons .moreButtonCatch');
moreBut.hide();
});
return this;
}
CatchAnnotation.prototype = {
init: function(){
// Set variables
// Initial Templates
this.TEMPLATENAMES = [
"annotationList", // Main
"annotationPublicPrivate", // Main->PublicPrivate
"annotationPublicPrivateInstructor", // Main->PublicPrivateInstructor
"annotationMediaSelector", // Main->MediaSelector
"annotationItem", // Main->ContainerRow
"annotationReply", // Main->ContainerRow->Reply
"annotationRow", // Main->ContainerRow->Row
"annotationDetail", // Main->ContainerRow->DetailRow
];
// annotator
var wrapper = $('.annotator-wrapper').parent()[0];
var annotator = $.data(wrapper, 'annotator');
this.annotator = annotator;
// Subscribe to annotator
this._subscribeAnnotator();
//
// Handlebars Register Library
//
Handlebars.registerHelper('deparagraph', function(txt) {
var dpg = txt.replace("<p>", "").replace("</p>", "");
return dpg;
});
// Compile templates
this.HTMLTEMPLATES = CatchSources.HTMLTEMPLATES(this.options.imageUrlRoot);
this.TEMPLATES = {};
this._compileTemplates();
// the default annotations are the user's personal ones instead of instructor.
// if the default tab is instructor, we must refresh the catch to pull the ones
// under the instructor's email. Calling changeUserId will update this.options.userId
// and most importantly refresh not only the highlights (from Annotator)
// but also the table below from the annotations database server (called Catch).
if(this.options.default_tab.toLowerCase() === 'instructor') {
this.changeUserId(this.options.instructor_email);
}
},
//
// GLOBAL UTILITIES
//
getTemplate: function(templateName) {
return this.TEMPLATES[templateName]() || '';
},
refreshCatch: function(newInstance) {
var mediaType = this.options.media || 'text';
var annotationItems = [];
var index = 0;
var annotations = this.annotator.plugins['Store'].annotations || [];
var el = $("#mainCatch.annotationListContainer");
var self = this;
var newInstance = newInstance || false;
annotations.forEach(function(annotation) {
var isMedia = annotation.media === self.options.media;
var isUser = (typeof self.options.userId !== 'undefined' && self.options.userId !== '' && self.options.userId !== null)?
self.options.userId === annotation.user.id:true;
var isInList = newInstance?false:self._isInList(annotation);
if (isMedia && isUser && !isInList) {
var item = jQuery.extend(true, {}, annotation);
self._formatCatch(item);
// Authorized
var permissions = self.annotator.plugins.Permissions;
var authorized = permissions.options.userAuthorize('delete', annotation, permissions.user);
var updateAuthorized = permissions.options.userAuthorize('update', annotation, permissions.user);
item.authToDeleteButton = authorized;
item.authToEditButton = updateAuthorized;
item.hasReplies = (item.totalComments > 0);
var html = self.TEMPLATES.annotationItem({
item: item,
id: item.id,
evenOrOdd: index % 2 ? "odd" : "even",
openOrClosed: "closed",
annotationRow: self.TEMPLATES.annotationRow(item),
annotationDetail: self.TEMPLATES.annotationDetail(item),
});
index++;
annotationItems.push(html);
}
});
if (newInstance) {
var videoFormat = (mediaType === "video") ? true : false;
var publicPrivateTemplate = '';
if (self.options.showPublicPrivate) {
var templateName = this.options.instructor_email ?
"annotationPublicPrivateInstructor" :
"annotationPublicPrivate";
}
el.html(self.TEMPLATES.annotationList({
annotationItems: annotationItems,
videoFormat: videoFormat,
PublicPrivate: this.getTemplate(templateName),
MediaSelector: self.options.showMediaSelector?self.TEMPLATES.annotationMediaSelector():'',
}));
} else {
var list = $("#mainCatch .annotationList");
annotationItems.forEach(function(annotation) {
list.append($(annotation));
});
}
// Set SelButtons to media
var SelButtons = el.find('.annotationList li').removeClass('active'); // reset
for (var index=0;index<SelButtons.length;index++) {
var span = $(SelButtons[index]);
if (span.attr("media") === this.options.media) $(SelButtons[index]).addClass('active');
}
// Set PublicPrivate
var PublicPrivateButtons = el.find('.annotationListButtons .PublicPrivate').removeClass('active'); // reset
for (var index=0;index<PublicPrivateButtons.length;index++) {
var span = $(PublicPrivateButtons[index]).find('span');
if (span.html().toLowerCase() === self.current_tab.toLowerCase()) {
switch (self.current_tab.toLowerCase()){
case 'public':
self.options.userId = '';
break;
case 'instructor':
self.options.userId = this.options.instructor_email;
break;
default:
self.options.userId = this.annotator.plugins.Permissions.user.id;
break;
}
$(PublicPrivateButtons[index]).addClass('active');
}
}
// reset all old events
el.off();
// Bind functions
var openAnnotationItem = this.__bind(this._openAnnotationItem, this);
var closeAnnotationItem = this.__bind(this._closeAnnotationItem, this);
var onGeolocationClick = this.__bind(this._onGeolocationClick, this);
var onPlaySelectionClick = this.__bind(this._onPlaySelectionClick, this);
var onShareControlsClick = this.__bind(this._onShareControlsClick, this);
var onSelectionButtonClick = this.__bind(this._onSelectionButtonClick, this);
var onPublicPrivateButtonClick = this.__bind(this._onPublicPrivateButtonClick, this);
var onQuoteMediaButton = this.__bind(this._onQuoteMediaButton, this);
var onControlRepliesClick = this.__bind(this._onControlRepliesClick, this);
var onMoreButtonClick = this.__bind(this._onMoreButtonClick, this);
var onSearchButtonClick = this.__bind(this._onSearchButtonClick, this);
var onClearSearchButtonClick = this.__bind(this._onClearSearchButtonClick, this);
var onDeleteReplyButtonClick = this.__bind(this._onDeleteReplyButtonClick, this);
var onZoomToImageBoundsButtonClick = this.__bind(this._onZoomToImageBoundsButtonClick, this);
var openLoadingGIF = this.__bind(this.openLoadingGIF, this);
//Open Button
el.on("click", ".annotationItem .annotationRow", openAnnotationItem);
// Close Button
el.on("click", ".annotationItem .detailHeader", closeAnnotationItem);
// Geolocation button
el.on("click", ".annotationItem .detailHeader .geolocationIcon img", onGeolocationClick);
// controlPanel buttons
el.on("click", ".annotationItem .annotationDetail .controlPanel", onShareControlsClick);
// VIDEO
if (this.options.media === 'video') {
// PlaySelection button
el.on("click", ".annotationItem .annotationDetail .playMediaButton", onPlaySelectionClick);
}
// TEXT
if (this.options.media === 'text') {
// PlaySelection button
el.on("click", ".annotationItem .annotationDetail .quote", onQuoteMediaButton);
}
// IMAGE
if (this.options.media === 'image') {
// PlaySelection button
el.on("click", ".annotationItem .annotationDetail .zoomToImageBounds", onZoomToImageBoundsButtonClick);
}
// controlReplies
el.on("click", ".annotationItem .controlReplies", onControlRepliesClick);
// Selection Buttons
el.on("click", ".annotationList li", onSelectionButtonClick);
// PublicPrivate Buttons
el.on("click", ".annotationListButtons .PublicPrivate", onPublicPrivateButtonClick);
// More Button
el.on("click", ".annotationListButtons .moreButtonCatch", onMoreButtonClick);
// Search Button
el.on("click", ".searchbox .search-icon", onSearchButtonClick);
// Search should also run when user hits ENTER
$('input[name=search]').keyup(function(e) {
// ENTER == 13
if(e.which == 13) {
onSearchButtonClick();
}
});
// Clear Search Button
el.on("click", ".searchbox .clear-search-icon", onClearSearchButtonClick);
// Delete Reply Button
el.on("click", ".replies .replyItem .deleteReply", onDeleteReplyButtonClick);
el.on("click", ".annotationListButtons .PublicPrivate", openLoadingGIF);
},
changeMedia: function(media) {
var media = media || 'text';
this.options.media = media;
this._refresh();
this.refreshCatch(true);
this.checkTotAnnotations();
},
changeUserId: function(userId) {
var userId = userId || '';
this.options.userId = userId;
this._refresh();
this.refreshCatch(true);
this.checkTotAnnotations();
},
/**
* This function makes sure that the annotations loaded are only the ones that we are
* currently looking for. Annotator has a habit of loading the user's annotations
* immediately without checking to see if we are doing some filtering or otherwise.
* Since it's a vendor file, this is the workaround for that bug.
*/
cleanUpAnnotations: function(){
var annotator = this.annotator;
var store = annotator.plugins.Store;
var annotations = store.annotations;
var self = this;
// goes through all the annotations currently loaded
$.each(annotations, function(key, value){
// if the options.userID (i.e. the value we are searching for) is empty signifying
// public or is equal to the person with update access, then we leave it alone,
// otherwise we need to clean them up (i.e. disable them).
if (self.options.userId !== '' && self.options.userId !== value.permissions.update[0]) {
if (value.highlights !== undefined) {
$.each(value.highlights, function(key1, value1){
$(value1).removeClass('annotator-hl');
});
}
}
});
},
loadAnnotations: function() {
var annotator = this.annotator;
var loadFromSearch = annotator.plugins.Store.options.loadFromSearch;
var loadedAn = this.element.find('.annotationList .annotationItem').length;
loadedAn = typeof loadedAn !== 'undefined' ?loadedAn:0;
loadFromSearch.limit = this.options.pagination;
loadFromSearch.offset = loadedAn;
loadFromSearch.media = this.options.media;
loadFromSearch.userid = this.options.userId;
// Dani had this for some reason. we can't remember. but if something
// breaks, uncomment next line.
// annotator.plugins['Store'].loadAnnotationsFromSearch(loadFromSearch);
// Make sure to be openned all annotations for this pagination
loadFromSearch.limit = this.options.pagination+loadedAn;
loadFromSearch.offset = 0;
annotator.plugins['Store'].loadAnnotationsFromSearch(loadFromSearch);
// text loading annotations
var moreBut = this.element.find('.annotationListButtons .moreButtonCatch');
moreBut.html('Please wait, loading...');
},
// check whether is necessary to have a more button or not
checkTotAnnotations: function() {
var annotator = this.annotator;
var loadFromSearch = annotator.plugins.Store.options.loadFromSearch;
var oldLimit = loadFromSearch.limit;
var oldOffset = loadFromSearch.offset;
var self = this;
loadFromSearch.limit = 0;
loadFromSearch.offset = 0;
loadFromSearch.media = this.options.media;
loadFromSearch.userid = this.options.userId;
var onSuccess = function(response) {
var totAn = self.element.find('.annotationList .annotationItem').length;
var maxAn = response.total;
var moreBut = self.element.find('.annotationListButtons .moreButtonCatch');
if (totAn<maxAn && totAn > 0)
moreBut.show();
else
moreBut.hide();
}
var obj = loadFromSearch;
var action = 'search';
var id, options, url;
id = obj && obj.id;
url = annotator.plugins['Store']._urlFor(action, id);
options = annotator.plugins['Store']._apiRequestOptions(action, obj, onSuccess);
$.ajax(url, options);
// reset values
loadFromSearch.limit = oldLimit;
loadFromSearch.offset = oldOffset;
// set More button text
var moreBut = this.element.find('.annotationListButtons .moreButtonCatch');
moreBut.html('More');
},
//
// LOCAL UTILITIES
//
_subscribeAnnotator: function() {
var self = this;
var annotator = this.annotator;
// Subscribe to Annotator changes
annotator.subscribe("annotationsLoaded", function (annotations) {
self.cleanUpAnnotations();
self.refreshCatch(self.clean);
// hide or show more button
self.checkTotAnnotations();
});
annotator.subscribe("annotationUpdated", function (annotation) {
self.refreshCatch(true);
self.checkTotAnnotations();
});
annotator.subscribe("annotationDeleted", function (annotation) {
var annotations = annotator.plugins['Store'].annotations;
var tot = typeof annotations !== 'undefined' ?annotations.length : 0;
var attempts = 0; // max 100
if(annotation.media === "image") {
self.refreshCatch(true);
self.checkTotAnnotations();
} else {
// This is to watch the annotations object, to see when is deleted the annotation
var ischanged = function() {
var new_tot = annotator.plugins['Store'].annotations.length;
if (attempts<100)
setTimeout(function() {
if (new_tot !== tot) {
self.refreshCatch(true);
self.checkTotAnnotations();
} else {
attempts++;
ischanged();
}
}, 100); // wait for the change in the annotations
};
ischanged();
}
});
annotator.subscribe("annotationCreated", function (annotation) {
var attempts = 0; // max 100
// There is a delay between calls to the backend--especially reading after
// writing. This function listens to when a function is created and waits
// until the server provides it with an annotation id before doing anything
// with it.
var ischanged = function(){
if (attempts<100)
setTimeout(function() {
if (typeof annotation.id !== 'undefined'){
// once it gets the annotation id, the table refreshes to show
// the edits
self.refreshCatch();
if (typeof annotation.parent !== 'undefined' && annotation.parent !== '0'){
// if annotation made was actually a replay to an annotation
// i.e. the only difference is that annotations that are
// not replies have no "parent"
var replies = $("[annotationid="+annotation.parent+"]").find(".controlReplies .hideReplies");
// forces "Show replies" section to show and then refreshes
// via two clicks
replies.show();
replies.click();
replies.click();
}
} else {
attempts++;
ischanged();
}
}, 100); // wait for annotation id
};
ischanged();
});
},
__bind: function(fn, me) { return function(){ return fn.apply(me, arguments); }; },
_compileTemplates: function() {
var self = this;
// Change the html tags to functions
this.TEMPLATENAMES.forEach(function(templateName) {
self.TEMPLATES[templateName] = Handlebars.compile(self.HTMLTEMPLATES[templateName]);
});
},
_isVideoJS: function (an) {
var annotator = this.annotator;
var rt = an.rangeTime;
var isOpenVideojs = (typeof annotator.mplayer !== 'undefined');
var isVideo = (typeof an.media !== 'undefined' && an.media === 'video');
var isNumber = (typeof rt !== 'undefined' && !isNaN(parseFloat(rt.start)) && isFinite(rt.start) && !isNaN(parseFloat(rt.end)) && isFinite(rt.end));
return (isOpenVideojs && isVideo && isNumber);
},
_isInList: function (an){
var annotator = this.annotator;
var isInList = false;
var list = $('#mainCatch .annotationList .annotationRow.item');
for (_i = 0, _len = list.length; _i < _len; _i++) {
if (parseInt($(list[_i]).parent().attr('annotationid'), 10) === an.id)
isInList = true;
}
return isInList;
},
_formatCatch: function(item) {
var item = item || {};
if (this._isVideoJS(item)) {
// format time
item.rangeTime.start= typeof vjs !== 'undefined' ?
vjs.formatTime(item.rangeTime.start) :
item.rangeTime.start;
item.rangeTime.end= typeof vjs !== 'undefined'?
vjs.formatTime(item.rangeTime.end) :
item.rangeTime.end;
}
// format date
if (typeof item.updated !== 'undefined' && typeof createDateFromISO8601 !== 'undefined')
item.updated = createDateFromISO8601(item.updated);
// format geolocation
if (typeof item.geolocation !== 'undefined' && (typeof item.geolocation.latitude === 'undefined' || item.geolocation.latitude === ''))
delete item.geolocation;
/* NEW VARIABLES */
// set plainText for Catch
item.plainText = item.text.replace(/&(lt|gt);/g, function (strMatch, p1){
return (p1 === "lt")? "<" : ">";
}); // Change to < and > tags
item.plainText = item.plainText.replace(/<\/?[^>]+(>|$)/g, "").replace('&nbsp;', ''); // remove all the html tags
item.mediatypeforgrid = {};
item.mediatypeforgrid[item.media] = true;
if (item.mediatypeforgrid.image) {
item.thumbnailLink = item.target.thumb;
};
// Flags
if (!this.options.flags && typeof item.tags !== 'undefined' && item.tags.length > 0) {
for (var len = item.tags.length, index = len-1; index >= 0; --index) {
var currTag = item.tags[index];
if (currTag.indexOf("flagged-") !== -1) {
item.tags.splice(index);
}
}
}
},
//
// EVENT HANDLER
//
_openAnnotationItem: function(evt) {
var isClosed = $(evt.currentTarget).closest(".annotationItem").hasClass("closed");
if (isClosed) {
$(evt.currentTarget).closest(".annotationItem").removeClass("closed").addClass("open");
// Add Share button
var shareControl = $(evt.currentTarget).closest(".annotationItem").find('.annotationDetail .controlPanel:first'),
annotator = this.annotator,
idAnnotation = shareControl.parent().find('.idAnnotation').html(),
uri = shareControl.parent().find('.uri').html();
// remove the last share container
shareControl.find('.share-container-annotator').remove();
shareControl.append(annotator.plugins.Share.buildHTMLShareButton("", idAnnotation));
// Set actions button
annotator.plugins.Share.buttonsActions(shareControl[0], 1, uri);
} else {
$(evt.currentTarget).closest(".annotationItem").removeClass("open").addClass("closed");
}
},
_closeAnnotationItem: function(evt) {
var existEvent = typeof evt.target !== 'undefined' && typeof evt.target.localName !== 'undefined';
if (existEvent && evt.target.parentNode.className !== 'geolocationIcon') {
this._openAnnotationItem(evt);
}
},
_onGeolocationClick: function(evt) {
var latitude = $(evt.target).parent().find('.latitude').html();
var longitude = $(evt.target).parent().find('.longitude').html();
var imgSrc = '<img src="http://maps.googleapis.com/maps/api/staticmap?center=' + latitude + ',' + longitude + '&zoom=14&size=500x500&sensor=false&markers=color:green%7Clabel:G%7C' + latitude + ',' + longitude + '">';
$(evt.target).parents('.detailHeader:first').find('#myLocationMap .map').html(imgSrc);
},
_onPlaySelectionClick: function(evt) {
var id = parseInt($(evt.target).find('.idAnnotation').html(), 10);
var uri = $(evt.target).find('.uri').html();
var container = $(evt.target).find('.container').html();
if (this.options.externalLink) {
uri += (uri.indexOf('?') >= 0) ? '&ovaId=' + id : '?ovaId=' + id;
location.href = uri;
} else {
var isContainer = typeof this.annotator.an !== 'undefined' && typeof this.annotator.an[container] !== 'undefined';
var ovaInstance = isContainer ? this.annotator.an[container] : null;
if (ovaInstance !== null) {
var allannotations = this.annotator.plugins['Store'].annotations,
ovaId = id,
player = ovaInstance.player;
for (var item in allannotations) {
var an = allannotations[item];
if (typeof an.id !== 'undefined' && an.id === ovaId) { // this is the annotation
if (this._isVideoJS(an)) { // It is a video
if (player.id_ === an.target.container && player.tech.options_.source.src === an.target.src) {
var anFound = an;
var playFunction = function(){
// Fix problem with youtube videos in the first play. The plugin don't have this trigger
if (player.techName === 'Youtube') {
var startAPI = function() {
ovaInstance.showAnnotation(anFound);
}
if (ovaInstance.loaded)
startAPI();
else
player.one('loadedRangeSlider', startAPI); // show Annotations once the RangeSlider is loaded
} else {
ovaInstance.showAnnotation(anFound);
}
$('html, body').animate({
scrollTop: $("#" + player.id_).offset().top},
'slow');
};
if (player.paused()) {
player.play();
player.one('playing', playFunction);
} else {
playFunction();
}
return false; // this will stop the code to not set a new player.one.
}
}
}
}
}
}
},
_onZoomToImageBoundsButtonClick: function(evt){
var zoomToBounds = $(evt.target).hasClass('zoomToImageBounds')?$(evt.target):$(evt.target).parents('.zoomToImageBounds:first');
var osdaId = parseInt(zoomToBounds.find('.idAnnotation').html(), 10);
var uri = zoomToBounds.find('.uri').html();
var allannotations = this.annotator.plugins['Store'].annotations;
var osda = this.annotator.osda;
if (this.options.externalLink) {
uri += (uri.indexOf('?') >= 0) ?'&osdaId=' + osdaId : '?osdaId=' + osdaId;
location.href = uri;
}
for(var item in allannotations) {
var an = allannotations[item];
// Makes sure that all images are set to transparent in case one was
// previously selected.
if (an.highlights) {
an.highlights[0].style.background = "rgba(0, 0, 0, 0)";
}
if (typeof an.id !== 'undefined' && an.id === osdaId) { // this is the annotation
var bounds = new OpenSeadragon.Rect(an.bounds.x, an.bounds.y, an.bounds.width, an.bounds.height);
osda.viewer.viewport.fitBounds(bounds, false);
$('html, body').animate({scrollTop: $("#"+an.target.container).offset().top},
'slow');
// signifies a selected annotation once OSD has zoomed in on the
// appropriate area, it turns the background a bit yellow
if (an.highlights !== undefined) {
an.highlights[0].style.background = "rgba(255, 255, 10, 0.2)";
}
}
}
},
_onQuoteMediaButton: function(evt) {
var quote = $(evt.target).hasClass('quote')?$(evt.target):$(evt.target).parents('.quote:first');
var id = parseInt(quote.find('.idAnnotation').html(), 10);
var uri = quote.find('.uri').html();
if (typeof id === 'undefined' || id === ''){
this.refreshCatch();
this.checkTotAnnotations();
id = quote.find('.idAnnotation').html();
// clickPlaySelection(evt);
}
if (this.options.externalLink) {
uri += (uri.indexOf('?') >= 0)?'&ovaId='+id:'?ovaId='+id;
location.href = uri;
} else {
var allannotations = this.annotator.plugins['Store'].annotations;
var ovaId = id;
for (var item in allannotations) {
var an = allannotations[item];
if (typeof an.id !== 'undefined' && an.id === ovaId) { // this is the annotation
if(!this._isVideoJS(an)) {
var hasRanges = typeof an.ranges !== 'undefined' && typeof an.ranges[0] !== 'undefined',
startOffset = hasRanges?an.ranges[0].startOffset:'',
endOffset = hasRanges?an.ranges[0].endOffset:'';
if (typeof startOffset !== 'undefined' && typeof endOffset !== 'undefined' && typeof an.highlights) {
$(an.highlights).parent().find('.annotator-hl').removeClass('api');
// change the color
$(an.highlights).addClass('api');
// animate to the annotation
$('html, body').animate({
scrollTop: $(an.highlights[0]).offset().top},
'slow');
}
}
}
}
}
},
_refreshReplies: function(evt) {
var item = $(evt.target).parents('.annotationItem:first');
var anId = parseInt(item.attr('annotationId'), 10);
var replyElem = $(evt.target).parents('.annotationItem:first').find('.replies');
var annotator = this.annotator;
var loadFromSearchURI = annotator.plugins.Store.options.loadFromSearch.uri;
var self = this;
var action='search';
var loadFromSearch={
limit:-1,
parentid:anId,
uri:loadFromSearchURI,
};
var onSuccess=function(data) {
if (data === null) data = {};
annotations = data.rows || [];
var _i, _len;
for (_i = 0, _len = annotations.length; _i < _len; _i++) {
self._formatCatch(annotations[_i]);
}
replyElem.html(self.TEMPLATES.annotationReply({
annotations: annotations
}));
var replyItems = $('.replies .replyItem');
if (typeof replyItems !== 'undefined' && replyItems.length > 0) {
annotations.forEach(function(ann) {
replyItems.each(function(item) {
var id = parseInt($(replyItems[item]).attr('annotationid'), 10);
if (id === ann.id) {
var perm = self.annotator.plugins.Permissions;
if (!perm.options.userAuthorize('delete', ann, perm.user)) {
$(replyItems[item]).find('.deleteReply').remove();
} else {
$(replyItems[item]).data('annotation', ann);
}
}
});
});
}
};
var id, options, request, url;
var store = this.annotator.plugins.Store;
id = loadFromSearch && loadFromSearch.id;
url = store._urlFor(action, id);
options = store._apiRequestOptions(action, loadFromSearch, onSuccess);
request = $.ajax(url, options);
request._id = id;
request._action = action;
},
_onControlRepliesClick: function(evt) {
var action = $(evt.target)[0].className;
if (action === 'newReply') {
var item = $(evt.target).parents('.annotationItem:first');
var id = item.attr('annotationId');
// Pre-show Adder
this.annotator.adder.show();
// Get elements
var replyElem = $(evt.target).parents('.annotationItem:first').find('.annotationDetail');
var adder =this.annotator.adder;
var wrapper = $('.annotator-wrapper');
// Calculate Editor position
var positionLeft = videojs.findPosition($(evt.target).parent().find('.newReply')[0]);
var positionAnnotator = videojs.findPosition(wrapper[0]);
var positionAdder = {};
// the following addition to display makes sure the editor shows up
// after opening TinyMCE/editor within the image source
positionAdder.display = "block";
positionAdder.left = positionLeft.left - positionAnnotator.left;
positionAdder.top = positionLeft.top + 20 - positionAnnotator.top;
adder.css(positionAdder);
// Open a new annotator dialog
this.annotator.onAdderClick();
// Set vertical editor
$(this.annotator.editor.element).css(positionAdder);
this.annotator.editor.resetOrientation();
this.annotator.editor.invertY();
// set parent
var parentValue = $(this.annotator.editor.element).find(".reply-item span.parent-annotation");
parentValue.html(id);
var self = this;
} else if (action === 'hideReplies') {
var oldAction = $(evt.target).html();
if (oldAction === 'Show Replies'){
$(evt.target).html('Hide Replies');
} else {
$(evt.target).html('Show Replies');
var replyElem = $(evt.target).parents('.annotationItem:first').find('.replies');
replyElem.html('');
return false;
}
// search
this._refreshReplies(evt);
} else if (action === 'deleteAnnotation') {
if (confirm("Would you like to delete the annotation?")) {
var annotator = this.annotator;
var item = $(evt.target).parents('.annotationItem:first');
var id = parseInt(item.attr('annotationId'), 10);
var store = annotator.plugins.Store;
var annotations = store.annotations;
var permissions = annotator.plugins.Permissions;
var annotation;
annotations.forEach(function(ann) {
if (ann.id === id)
annotation = ann;
});
var authorized = permissions.options.userAuthorize('delete', annotation, permissions.user);
if (authorized)
annotator.deleteAnnotation(annotation);
}
} else if (action === 'editAnnotation') {
var annotator = this.annotator;
var item = $(evt.target).parents('.annotationItem:first');
var id = parseInt(item.attr('annotationId'), 10);
var store = annotator.plugins.Store;
var annotations = store.annotations;
var permissions = annotator.plugins.Permissions;
var annotation;
annotations.forEach(function(ann) {
if (ann.id === id)
annotation = ann;
});
var authorized = permissions.options.userAuthorize('update', annotation, permissions.user);
if (authorized){
// Get elements
var wrapper = $('.annotator-wrapper');
// Calculate Editor position
var positionLeft = videojs.findPosition($(evt.target).parent().find('.editAnnotation')[0]);
var positionAnnotator = videojs.findPosition(wrapper[0]);
var positionAdder = {};
positionAdder.left = positionLeft.left - positionAnnotator.left;
positionAdder.top = positionLeft.top + 20 - positionAnnotator.top;
var cleanup, offset, update;
var _this = this.annotator;
offset = positionAdder;
update = function() {
cleanup();
return _this.updateAnnotation(annotation);
};
cleanup = function() {
_this.unsubscribe('annotationEditorHidden', cleanup);
return _this.unsubscribe('annotationEditorSubmit', update);
};
this.annotator.subscribe('annotationEditorHidden', cleanup);
this.annotator.subscribe('annotationEditorSubmit', update);
this.annotator.viewer.hide();
this.annotator.showEditor(annotation, offset);
}
}
},
_onShareControlsClick: function(evt) {
var action = $(evt.target)[0].className;
if (action === 'privacy_button') {
} else if (action === 'groups_button') {
alert("Coming soon...");
} else if (action === 'reply_button') {
var item = $(evt.target).parents('.annotationItem:first'),
id = item.attr('annotationId');
// New annotation
var an = this.annotator.setupAnnotation(this.annotator.createAnnotation());
an.text="010";
an.parent = id;
} else if (action === 'share_button') {
}
},
_onPublicPrivateButtonClick: function(evt) {
var action = $(evt.target).find('span');
var userId = '';
// Get userI
switch (action.html()){
case 'public':
userId = '';
break;
case 'instructor':
userId = this.options.instructor_email;
break;
default:
userId = this.annotator.plugins.Permissions.user.id;
break;
}
this.current_tab = action.html();
// checks to make sure that Grouping is redone when switching tags in text annotations
if (this.options.media === 'text') {
if (typeof this.annotator.plugins.Grouping !== 'undefined') {
// this is to check if user is is MyNotes instead of the annotation component
this.annotator.plugins.Grouping.useGrouping = this.current_tab === 'public' ? 0 : 1;
}
this.annotator.publish("changedTabsInCatch");
}
// Change userid and refresh
this.changeUserId(userId);
},
_onSelectionButtonClick: function(evt) {
var but = $(evt.target);
var action = but.attr('media');
// Get action
if (action.length<=0) action="text"; // By default
// Change media and refresh
this.changeMedia(action);
},
_onMoreButtonClick: function(evt) {
this.clean = false;
var moreBut = this.element.find('.annotationListButtons .moreButtonCatch');
var isLoading = moreBut.html() === 'More'?false:true;
if(!isLoading)
this.loadAnnotations();
},
_refresh:function(searchtype, searchInput) {
var searchtype = searchtype || "";
var searchInput = searchInput || "";
this.clean = true;
// the following cannot run in notes for there are no highlights
if ($("#notesHolder").length === 0) {
this._clearAnnotator();
}
var annotator = this.annotator;
var loadFromSearch = annotator.plugins.Store.options.loadFromSearch;
loadFromSearch.limit = this.options.pagination;
loadFromSearch.offset = 0;
loadFromSearch.media = this.options.media;
loadFromSearch.userid = this.options.userId;
loadFromSearch.username = "";
loadFromSearch.tag = "";
loadFromSearch.text = "";
if (searchtype === "Users") {
loadFromSearch.username = searchInput;
} else if(searchtype === "Tags") {
loadFromSearch.tag = searchInput;
} else {
loadFromSearch.text = searchInput;
}
annotator.plugins['Store'].loadAnnotationsFromSearch(loadFromSearch);
},
_onSearchButtonClick: function(evt) {
var searchtype = this.element.find('.searchbox .dropdown-list').val();
var searchInput = this.element.find('.searchbox input').val();
this._refresh(searchtype, searchInput);
},
_onClearSearchButtonClick: function(evt) {
this._refresh('', '');
},
_clearAnnotator: function() {
var annotator = this.annotator;
var store = annotator.plugins.Store;
var annotations = store.annotations.slice();
annotations.forEach(function(ann){
var child, h, _i, _len, _ref;
if (ann.highlights !== undefined) {
_ref = ann.highlights;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
h = _ref[_i];
if (!(h.parentNode !== undefined)) {
continue;
}
child = h.childNodes[0];
$(h).replaceWith(h.childNodes);
}
}
store.unregisterAnnotation(ann);
});
},
_onDeleteReplyButtonClick : function(evt) {
var annotator = this.annotator;
var item = $(evt.target).parents('.replyItem:first');
var id = item.attr('annotationid');
var permissions = annotator.plugins.Permissions;
var annotation = item.data('annotation');
var authorized = permissions.options.userAuthorize('delete', annotation, permissions.user);
if(authorized){
if(confirm('Would you like to delete this reply?')){
annotator.plugins['Store']._apiRequest('destroy', annotation, function(){});
item.remove();
}
}
},
openLoadingGIF: function() {
$('#mainCatch').append('<div class=\'annotations-loading-gif\'><img src="'+this.options.imageUrlRoot+'loading_bar.gif" /><br />Annotations Data Loading... Please Wait.</div>');
},
}

View File

@@ -1,2595 +0,0 @@
/*!
handlebars v1.1.2
Copyright (C) 2011 by Yehuda Katz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@license
*/
var Handlebars = (function() {
// handlebars/safe-string.js
var __module4__ = (function() {
"use strict";
var __exports__;
// Build out our basic SafeString type
function SafeString(string) {
this.string = string;
}
SafeString.prototype.toString = function() {
return "" + this.string;
};
__exports__ = SafeString;
return __exports__;
})();
// handlebars/utils.js
var __module3__ = (function(__dependency1__) {
"use strict";
var __exports__ = {};
var SafeString = __dependency1__;
var escape = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': "&quot;",
"'": "&#x27;",
"`": "&#x60;"
};
var badChars = /[&<>"'`]/g;
var possible = /[&<>"'`]/;
function escapeChar(chr) {
return escape[chr] || "&amp;";
}
function extend(obj, value) {
for(var key in value) {
if(value.hasOwnProperty(key)) {
obj[key] = value[key];
}
}
}
__exports__.extend = extend;var toString = Object.prototype.toString;
__exports__.toString = toString;
// Sourced from lodash
// https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
var isFunction = function(value) {
return typeof value === 'function';
};
// fallback for older versions of Chrome and Safari
if (isFunction(/x/)) {
isFunction = function(value) {
return typeof value === 'function' && toString.call(value) === '[object Function]';
};
}
var isFunction;
__exports__.isFunction = isFunction;
var isArray = Array.isArray || function(value) {
return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false;
};
__exports__.isArray = isArray;
function escapeExpression(string) {
// don't escape SafeStrings, since they're already safe
if (string instanceof SafeString) {
return string.toString();
} else if (!string && string !== 0) {
return "";
}
// Force a string conversion as this will be done by the append regardless and
// the regex test will do this transparently behind the scenes, causing issues if
// an object's to string has escaped characters in it.
string = "" + string;
if(!possible.test(string)) { return string; }
return string.replace(badChars, escapeChar);
}
__exports__.escapeExpression = escapeExpression;function isEmpty(value) {
if (!value && value !== 0) {
return true;
} else if (isArray(value) && value.length === 0) {
return true;
} else {
return false;
}
}
__exports__.isEmpty = isEmpty;
return __exports__;
})(__module4__);
// handlebars/exception.js
var __module5__ = (function() {
"use strict";
var __exports__;
var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
function Exception(/* message */) {
var tmp = Error.prototype.constructor.apply(this, arguments);
// Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
for (var idx = 0; idx < errorProps.length; idx++) {
this[errorProps[idx]] = tmp[errorProps[idx]];
}
}
Exception.prototype = new Error();
__exports__ = Exception;
return __exports__;
})();
// handlebars/base.js
var __module2__ = (function(__dependency1__, __dependency2__) {
"use strict";
var __exports__ = {};
/*globals Exception, Utils */
var Utils = __dependency1__;
var Exception = __dependency2__;
var VERSION = "1.1.2";
__exports__.VERSION = VERSION;var COMPILER_REVISION = 4;
__exports__.COMPILER_REVISION = COMPILER_REVISION;
var REVISION_CHANGES = {
1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
2: '== 1.0.0-rc.3',
3: '== 1.0.0-rc.4',
4: '>= 1.0.0'
};
__exports__.REVISION_CHANGES = REVISION_CHANGES;
var isArray = Utils.isArray,
isFunction = Utils.isFunction,
toString = Utils.toString,
objectType = '[object Object]';
function HandlebarsEnvironment(helpers, partials) {
this.helpers = helpers || {};
this.partials = partials || {};
registerDefaultHelpers(this);
}
__exports__.HandlebarsEnvironment = HandlebarsEnvironment;HandlebarsEnvironment.prototype = {
constructor: HandlebarsEnvironment,
logger: logger,
log: log,
registerHelper: function(name, fn, inverse) {
if (toString.call(name) === objectType) {
if (inverse || fn) { throw new Exception('Arg not supported with multiple helpers'); }
Utils.extend(this.helpers, name);
} else {
if (inverse) { fn.not = inverse; }
this.helpers[name] = fn;
}
},
registerPartial: function(name, str) {
if (toString.call(name) === objectType) {
Utils.extend(this.partials, name);
} else {
this.partials[name] = str;
}
}
};
function registerDefaultHelpers(instance) {
instance.registerHelper('helperMissing', function(arg) {
if(arguments.length === 2) {
return undefined;
} else {
throw new Error("Missing helper: '" + arg + "'");
}
});
instance.registerHelper('blockHelperMissing', function(context, options) {
var inverse = options.inverse || function() {}, fn = options.fn;
if (isFunction(context)) { context = context.call(this); }
if(context === true) {
return fn(this);
} else if(context === false || context == null) {
return inverse(this);
} else if (isArray(context)) {
if(context.length > 0) {
return instance.helpers.each(context, options);
} else {
return inverse(this);
}
} else {
return fn(context);
}
});
instance.registerHelper('each', function(context, options) {
var fn = options.fn, inverse = options.inverse;
var i = 0, ret = "", data;
if (isFunction(context)) { context = context.call(this); }
if (options.data) {
data = createFrame(options.data);
}
if(context && typeof context === 'object') {
if (isArray(context)) {
for(var j = context.length; i<j; i++) {
if (data) {
data.index = i;
data.first = (i === 0)
data.last = (i === (context.length-1));
}
ret = ret + fn(context[i], { data: data });
}
} else {
for(var key in context) {
if(context.hasOwnProperty(key)) {
if(data) { data.key = key; }
ret = ret + fn(context[key], {data: data});
i++;
}
}
}
}
if(i === 0){
ret = inverse(this);
}
return ret;
});
instance.registerHelper('if', function(conditional, options) {
if (isFunction(conditional)) { conditional = conditional.call(this); }
// Default behavior is to render the positive path if the value is truthy and not empty.
// The `includeZero` option may be set to treat the condtional as purely not empty based on the
// behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
if ((!options.hash.includeZero && !conditional) || Utils.isEmpty(conditional)) {
return options.inverse(this);
} else {
return options.fn(this);
}
});
instance.registerHelper('unless', function(conditional, options) {
return instance.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn, hash: options.hash});
});
instance.registerHelper('with', function(context, options) {
if (isFunction(context)) { context = context.call(this); }
if (!Utils.isEmpty(context)) return options.fn(context);
});
instance.registerHelper('log', function(context, options) {
var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
instance.log(level, context);
});
}
var logger = {
methodMap: { 0: 'debug', 1: 'info', 2: 'warn', 3: 'error' },
// State enum
DEBUG: 0,
INFO: 1,
WARN: 2,
ERROR: 3,
level: 3,
// can be overridden in the host environment
log: function(level, obj) {
if (logger.level <= level) {
var method = logger.methodMap[level];
if (typeof console !== 'undefined' && console[method]) {
console[method].call(console, obj);
}
}
}
};
__exports__.logger = logger;
function log(level, obj) { logger.log(level, obj); }
__exports__.log = log;var createFrame = function(object) {
var obj = {};
Utils.extend(obj, object);
return obj;
};
__exports__.createFrame = createFrame;
return __exports__;
})(__module3__, __module5__);
// handlebars/runtime.js
var __module6__ = (function(__dependency1__, __dependency2__, __dependency3__) {
"use strict";
var __exports__ = {};
/*global Utils */
var Utils = __dependency1__;
var Exception = __dependency2__;
var COMPILER_REVISION = __dependency3__.COMPILER_REVISION;
var REVISION_CHANGES = __dependency3__.REVISION_CHANGES;
function checkRevision(compilerInfo) {
var compilerRevision = compilerInfo && compilerInfo[0] || 1,
currentRevision = COMPILER_REVISION;
if (compilerRevision !== currentRevision) {
if (compilerRevision < currentRevision) {
var runtimeVersions = REVISION_CHANGES[currentRevision],
compilerVersions = REVISION_CHANGES[compilerRevision];
throw new Error("Template was precompiled with an older version of Handlebars than the current runtime. "+
"Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").");
} else {
// Use the embedded version info since the runtime doesn't know about this revision yet
throw new Error("Template was precompiled with a newer version of Handlebars than the current runtime. "+
"Please update your runtime to a newer version ("+compilerInfo[1]+").");
}
}
}
// TODO: Remove this line and break up compilePartial
function template(templateSpec, env) {
if (!env) {
throw new Error("No environment passed to template");
}
var invokePartialWrapper;
if (env.compile) {
invokePartialWrapper = function(partial, name, context, helpers, partials, data) {
// TODO : Check this for all inputs and the options handling (partial flag, etc). This feels
// like there should be a common exec path
var result = invokePartial.apply(this, arguments);
if (result) { return result; }
var options = { helpers: helpers, partials: partials, data: data };
partials[name] = env.compile(partial, { data: data !== undefined }, env);
return partials[name](context, options);
};
} else {
invokePartialWrapper = function(partial, name /* , context, helpers, partials, data */) {
var result = invokePartial.apply(this, arguments);
if (result) { return result; }
throw new Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
};
}
// Just add water
var container = {
escapeExpression: Utils.escapeExpression,
invokePartial: invokePartialWrapper,
programs: [],
program: function(i, fn, data) {
var programWrapper = this.programs[i];
if(data) {
programWrapper = program(i, fn, data);
} else if (!programWrapper) {
programWrapper = this.programs[i] = program(i, fn);
}
return programWrapper;
},
merge: function(param, common) {
var ret = param || common;
if (param && common && (param !== common)) {
ret = {};
Utils.extend(ret, common);
Utils.extend(ret, param);
}
return ret;
},
programWithDepth: programWithDepth,
noop: noop,
compilerInfo: null
};
return function(context, options) {
options = options || {};
var namespace = options.partial ? options : env,
helpers,
partials;
if (!options.partial) {
helpers = options.helpers;
partials = options.partials;
}
var result = templateSpec.call(
container,
namespace, context,
helpers,
partials,
options.data);
if (!options.partial) {
checkRevision(container.compilerInfo);
}
return result;
};
}
__exports__.template = template;function programWithDepth(i, fn, data /*, $depth */) {
var args = Array.prototype.slice.call(arguments, 3);
var prog = function(context, options) {
options = options || {};
return fn.apply(this, [context, options.data || data].concat(args));
};
prog.program = i;
prog.depth = args.length;
return prog;
}
__exports__.programWithDepth = programWithDepth;function program(i, fn, data) {
var prog = function(context, options) {
options = options || {};
return fn(context, options.data || data);
};
prog.program = i;
prog.depth = 0;
return prog;
}
__exports__.program = program;function invokePartial(partial, name, context, helpers, partials, data) {
var options = { partial: true, helpers: helpers, partials: partials, data: data };
if(partial === undefined) {
throw new Exception("The partial " + name + " could not be found");
} else if(partial instanceof Function) {
return partial(context, options);
}
}
__exports__.invokePartial = invokePartial;function noop() { return ""; }
__exports__.noop = noop;
return __exports__;
})(__module3__, __module5__, __module2__);
// handlebars.runtime.js
var __module1__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
"use strict";
var __exports__;
var base = __dependency1__;
// Each of these augment the Handlebars object. No need to setup here.
// (This is done to easily share code between commonjs and browse envs)
var SafeString = __dependency2__;
var Exception = __dependency3__;
var Utils = __dependency4__;
var runtime = __dependency5__;
// For compatibility and usage outside of module systems, make the Handlebars object a namespace
var create = function() {
var hb = new base.HandlebarsEnvironment();
Utils.extend(hb, base);
hb.SafeString = SafeString;
hb.Exception = Exception;
hb.Utils = Utils;
hb.VM = runtime;
hb.template = function(spec) {
return runtime.template(spec, hb);
};
return hb;
};
var Handlebars = create();
Handlebars.create = create;
__exports__ = Handlebars;
return __exports__;
})(__module2__, __module4__, __module5__, __module3__, __module6__);
// handlebars/compiler/ast.js
var __module7__ = (function(__dependency1__) {
"use strict";
var __exports__ = {};
var Exception = __dependency1__;
function ProgramNode(statements, inverseStrip, inverse) {
this.type = "program";
this.statements = statements;
this.strip = {};
if(inverse) {
this.inverse = new ProgramNode(inverse, inverseStrip);
this.strip.right = inverseStrip.left;
} else if (inverseStrip) {
this.strip.left = inverseStrip.right;
}
}
__exports__.ProgramNode = ProgramNode;function MustacheNode(rawParams, hash, open, strip) {
this.type = "mustache";
this.hash = hash;
this.strip = strip;
var escapeFlag = open[3] || open[2];
this.escaped = escapeFlag !== '{' && escapeFlag !== '&';
var id = this.id = rawParams[0];
var params = this.params = rawParams.slice(1);
// a mustache is an eligible helper if:
// * its id is simple (a single part, not `this` or `..`)
var eligibleHelper = this.eligibleHelper = id.isSimple;
// a mustache is definitely a helper if:
// * it is an eligible helper, and
// * it has at least one parameter or hash segment
this.isHelper = eligibleHelper && (params.length || hash);
// if a mustache is an eligible helper but not a definite
// helper, it is ambiguous, and will be resolved in a later
// pass or at runtime.
}
__exports__.MustacheNode = MustacheNode;function PartialNode(partialName, context, strip) {
this.type = "partial";
this.partialName = partialName;
this.context = context;
this.strip = strip;
}
__exports__.PartialNode = PartialNode;function BlockNode(mustache, program, inverse, close) {
if(mustache.id.original !== close.path.original) {
throw new Exception(mustache.id.original + " doesn't match " + close.path.original);
}
this.type = "block";
this.mustache = mustache;
this.program = program;
this.inverse = inverse;
this.strip = {
left: mustache.strip.left,
right: close.strip.right
};
(program || inverse).strip.left = mustache.strip.right;
(inverse || program).strip.right = close.strip.left;
if (inverse && !program) {
this.isInverse = true;
}
}
__exports__.BlockNode = BlockNode;function ContentNode(string) {
this.type = "content";
this.string = string;
}
__exports__.ContentNode = ContentNode;function HashNode(pairs) {
this.type = "hash";
this.pairs = pairs;
}
__exports__.HashNode = HashNode;function IdNode(parts) {
this.type = "ID";
var original = "",
dig = [],
depth = 0;
for(var i=0,l=parts.length; i<l; i++) {
var part = parts[i].part;
original += (parts[i].separator || '') + part;
if (part === ".." || part === "." || part === "this") {
if (dig.length > 0) { throw new Exception("Invalid path: " + original); }
else if (part === "..") { depth++; }
else { this.isScoped = true; }
}
else { dig.push(part); }
}
this.original = original;
this.parts = dig;
this.string = dig.join('.');
this.depth = depth;
// an ID is simple if it only has one part, and that part is not
// `..` or `this`.
this.isSimple = parts.length === 1 && !this.isScoped && depth === 0;
this.stringModeValue = this.string;
}
__exports__.IdNode = IdNode;function PartialNameNode(name) {
this.type = "PARTIAL_NAME";
this.name = name.original;
}
__exports__.PartialNameNode = PartialNameNode;function DataNode(id) {
this.type = "DATA";
this.id = id;
}
__exports__.DataNode = DataNode;function StringNode(string) {
this.type = "STRING";
this.original =
this.string =
this.stringModeValue = string;
}
__exports__.StringNode = StringNode;function IntegerNode(integer) {
this.type = "INTEGER";
this.original =
this.integer = integer;
this.stringModeValue = Number(integer);
}
__exports__.IntegerNode = IntegerNode;function BooleanNode(bool) {
this.type = "BOOLEAN";
this.bool = bool;
this.stringModeValue = bool === "true";
}
__exports__.BooleanNode = BooleanNode;function CommentNode(comment) {
this.type = "comment";
this.comment = comment;
}
__exports__.CommentNode = CommentNode;
return __exports__;
})(__module5__);
// handlebars/compiler/parser.js
var __module9__ = (function() {
"use strict";
var __exports__;
/* Jison generated parser */
var handlebars = (function(){
var parser = {trace: function trace() { },
yy: {},
symbols_: {"error":2,"root":3,"statements":4,"EOF":5,"program":6,"simpleInverse":7,"statement":8,"openInverse":9,"closeBlock":10,"openBlock":11,"mustache":12,"partial":13,"CONTENT":14,"COMMENT":15,"OPEN_BLOCK":16,"inMustache":17,"CLOSE":18,"OPEN_INVERSE":19,"OPEN_ENDBLOCK":20,"path":21,"OPEN":22,"OPEN_UNESCAPED":23,"CLOSE_UNESCAPED":24,"OPEN_PARTIAL":25,"partialName":26,"partial_option0":27,"inMustache_repetition0":28,"inMustache_option0":29,"dataName":30,"param":31,"STRING":32,"INTEGER":33,"BOOLEAN":34,"hash":35,"hash_repetition_plus0":36,"hashSegment":37,"ID":38,"EQUALS":39,"DATA":40,"pathSegments":41,"SEP":42,"$accept":0,"$end":1},
terminals_: {2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"CLOSE_UNESCAPED",25:"OPEN_PARTIAL",32:"STRING",33:"INTEGER",34:"BOOLEAN",38:"ID",39:"EQUALS",40:"DATA",42:"SEP"},
productions_: [0,[3,2],[3,1],[6,2],[6,3],[6,2],[6,1],[6,1],[6,0],[4,1],[4,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,4],[7,2],[17,3],[17,1],[31,1],[31,1],[31,1],[31,1],[31,1],[35,1],[37,3],[26,1],[26,1],[26,1],[30,2],[21,1],[41,3],[41,1],[27,0],[27,1],[28,0],[28,2],[29,0],[29,1],[36,1],[36,2]],
performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
var $0 = $$.length - 1;
switch (yystate) {
case 1: return new yy.ProgramNode($$[$0-1]);
break;
case 2: return new yy.ProgramNode([]);
break;
case 3:this.$ = new yy.ProgramNode([], $$[$0-1], $$[$0]);
break;
case 4:this.$ = new yy.ProgramNode($$[$0-2], $$[$0-1], $$[$0]);
break;
case 5:this.$ = new yy.ProgramNode($$[$0-1], $$[$0], []);
break;
case 6:this.$ = new yy.ProgramNode($$[$0]);
break;
case 7:this.$ = new yy.ProgramNode([]);
break;
case 8:this.$ = new yy.ProgramNode([]);
break;
case 9:this.$ = [$$[$0]];
break;
case 10: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
break;
case 11:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1].inverse, $$[$0-1], $$[$0]);
break;
case 12:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0-1].inverse, $$[$0]);
break;
case 13:this.$ = $$[$0];
break;
case 14:this.$ = $$[$0];
break;
case 15:this.$ = new yy.ContentNode($$[$0]);
break;
case 16:this.$ = new yy.CommentNode($$[$0]);
break;
case 17:this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], $$[$0-2], stripFlags($$[$0-2], $$[$0]));
break;
case 18:this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], $$[$0-2], stripFlags($$[$0-2], $$[$0]));
break;
case 19:this.$ = {path: $$[$0-1], strip: stripFlags($$[$0-2], $$[$0])};
break;
case 20:this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], $$[$0-2], stripFlags($$[$0-2], $$[$0]));
break;
case 21:this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], $$[$0-2], stripFlags($$[$0-2], $$[$0]));
break;
case 22:this.$ = new yy.PartialNode($$[$0-2], $$[$0-1], stripFlags($$[$0-3], $$[$0]));
break;
case 23:this.$ = stripFlags($$[$0-1], $$[$0]);
break;
case 24:this.$ = [[$$[$0-2]].concat($$[$0-1]), $$[$0]];
break;
case 25:this.$ = [[$$[$0]], null];
break;
case 26:this.$ = $$[$0];
break;
case 27:this.$ = new yy.StringNode($$[$0]);
break;
case 28:this.$ = new yy.IntegerNode($$[$0]);
break;
case 29:this.$ = new yy.BooleanNode($$[$0]);
break;
case 30:this.$ = $$[$0];
break;
case 31:this.$ = new yy.HashNode($$[$0]);
break;
case 32:this.$ = [$$[$0-2], $$[$0]];
break;
case 33:this.$ = new yy.PartialNameNode($$[$0]);
break;
case 34:this.$ = new yy.PartialNameNode(new yy.StringNode($$[$0]));
break;
case 35:this.$ = new yy.PartialNameNode(new yy.IntegerNode($$[$0]));
break;
case 36:this.$ = new yy.DataNode($$[$0]);
break;
case 37:this.$ = new yy.IdNode($$[$0]);
break;
case 38: $$[$0-2].push({part: $$[$0], separator: $$[$0-1]}); this.$ = $$[$0-2];
break;
case 39:this.$ = [{part: $$[$0]}];
break;
case 42:this.$ = [];
break;
case 43:$$[$0-1].push($$[$0]);
break;
case 46:this.$ = [$$[$0]];
break;
case 47:$$[$0-1].push($$[$0]);
break;
}
},
table: [{3:1,4:2,5:[1,3],8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[3]},{5:[1,16],8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[2,2]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],25:[2,9]},{4:20,6:18,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{4:20,6:22,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{5:[2,13],14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],25:[2,13]},{5:[2,14],14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],25:[2,14]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],25:[2,15]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],25:[2,16]},{17:23,21:24,30:25,38:[1,28],40:[1,27],41:26},{17:29,21:24,30:25,38:[1,28],40:[1,27],41:26},{17:30,21:24,30:25,38:[1,28],40:[1,27],41:26},{17:31,21:24,30:25,38:[1,28],40:[1,27],41:26},{21:33,26:32,32:[1,34],33:[1,35],38:[1,28],41:26},{1:[2,1]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],25:[2,10]},{10:36,20:[1,37]},{4:38,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,7],22:[1,13],23:[1,14],25:[1,15]},{7:39,8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,6],22:[1,13],23:[1,14],25:[1,15]},{17:23,18:[1,40],21:24,30:25,38:[1,28],40:[1,27],41:26},{10:41,20:[1,37]},{18:[1,42]},{18:[2,42],24:[2,42],28:43,32:[2,42],33:[2,42],34:[2,42],38:[2,42],40:[2,42]},{18:[2,25],24:[2,25]},{18:[2,37],24:[2,37],32:[2,37],33:[2,37],34:[2,37],38:[2,37],40:[2,37],42:[1,44]},{21:45,38:[1,28],41:26},{18:[2,39],24:[2,39],32:[2,39],33:[2,39],34:[2,39],38:[2,39],40:[2,39],42:[2,39]},{18:[1,46]},{18:[1,47]},{24:[1,48]},{18:[2,40],21:50,27:49,38:[1,28],41:26},{18:[2,33],38:[2,33]},{18:[2,34],38:[2,34]},{18:[2,35],38:[2,35]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],25:[2,11]},{21:51,38:[1,28],41:26},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,3],22:[1,13],23:[1,14],25:[1,15]},{4:52,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,5],22:[1,13],23:[1,14],25:[1,15]},{14:[2,23],15:[2,23],16:[2,23],19:[2,23],20:[2,23],22:[2,23],23:[2,23],25:[2,23]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],25:[2,12]},{14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],25:[2,18]},{18:[2,44],21:56,24:[2,44],29:53,30:60,31:54,32:[1,57],33:[1,58],34:[1,59],35:55,36:61,37:62,38:[1,63],40:[1,27],41:26},{38:[1,64]},{18:[2,36],24:[2,36],32:[2,36],33:[2,36],34:[2,36],38:[2,36],40:[2,36]},{14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],25:[2,17]},{5:[2,20],14:[2,20],15:[2,20],16:[2,20],19:[2,20],20:[2,20],22:[2,20],23:[2,20],25:[2,20]},{5:[2,21],14:[2,21],15:[2,21],16:[2,21],19:[2,21],20:[2,21],22:[2,21],23:[2,21],25:[2,21]},{18:[1,65]},{18:[2,41]},{18:[1,66]},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],25:[1,15]},{18:[2,24],24:[2,24]},{18:[2,43],24:[2,43],32:[2,43],33:[2,43],34:[2,43],38:[2,43],40:[2,43]},{18:[2,45],24:[2,45]},{18:[2,26],24:[2,26],32:[2,26],33:[2,26],34:[2,26],38:[2,26],40:[2,26]},{18:[2,27],24:[2,27],32:[2,27],33:[2,27],34:[2,27],38:[2,27],40:[2,27]},{18:[2,28],24:[2,28],32:[2,28],33:[2,28],34:[2,28],38:[2,28],40:[2,28]},{18:[2,29],24:[2,29],32:[2,29],33:[2,29],34:[2,29],38:[2,29],40:[2,29]},{18:[2,30],24:[2,30],32:[2,30],33:[2,30],34:[2,30],38:[2,30],40:[2,30]},{18:[2,31],24:[2,31],37:67,38:[1,68]},{18:[2,46],24:[2,46],38:[2,46]},{18:[2,39],24:[2,39],32:[2,39],33:[2,39],34:[2,39],38:[2,39],39:[1,69],40:[2,39],42:[2,39]},{18:[2,38],24:[2,38],32:[2,38],33:[2,38],34:[2,38],38:[2,38],40:[2,38],42:[2,38]},{5:[2,22],14:[2,22],15:[2,22],16:[2,22],19:[2,22],20:[2,22],22:[2,22],23:[2,22],25:[2,22]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],25:[2,19]},{18:[2,47],24:[2,47],38:[2,47]},{39:[1,69]},{21:56,30:60,31:70,32:[1,57],33:[1,58],34:[1,59],38:[1,28],40:[1,27],41:26},{18:[2,32],24:[2,32],38:[2,32]}],
defaultActions: {3:[2,2],16:[2,1],50:[2,41]},
parseError: function parseError(str, hash) {
throw new Error(str);
},
parse: function parse(input) {
var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
this.lexer.setInput(input);
this.lexer.yy = this.yy;
this.yy.lexer = this.lexer;
this.yy.parser = this;
if (typeof this.lexer.yylloc == "undefined")
this.lexer.yylloc = {};
var yyloc = this.lexer.yylloc;
lstack.push(yyloc);
var ranges = this.lexer.options && this.lexer.options.ranges;
if (typeof this.yy.parseError === "function")
this.parseError = this.yy.parseError;
function popStack(n) {
stack.length = stack.length - 2 * n;
vstack.length = vstack.length - n;
lstack.length = lstack.length - n;
}
function lex() {
var token;
token = self.lexer.lex() || 1;
if (typeof token !== "number") {
token = self.symbols_[token] || token;
}
return token;
}
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
while (true) {
state = stack[stack.length - 1];
if (this.defaultActions[state]) {
action = this.defaultActions[state];
} else {
if (symbol === null || typeof symbol == "undefined") {
symbol = lex();
}
action = table[state] && table[state][symbol];
}
if (typeof action === "undefined" || !action.length || !action[0]) {
var errStr = "";
if (!recovering) {
expected = [];
for (p in table[state])
if (this.terminals_[p] && p > 2) {
expected.push("'" + this.terminals_[p] + "'");
}
if (this.lexer.showPosition) {
errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
} else {
errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'");
}
this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
}
}
if (action[0] instanceof Array && action.length > 1) {
throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
}
switch (action[0]) {
case 1:
stack.push(symbol);
vstack.push(this.lexer.yytext);
lstack.push(this.lexer.yylloc);
stack.push(action[1]);
symbol = null;
if (!preErrorSymbol) {
yyleng = this.lexer.yyleng;
yytext = this.lexer.yytext;
yylineno = this.lexer.yylineno;
yyloc = this.lexer.yylloc;
if (recovering > 0)
recovering--;
} else {
symbol = preErrorSymbol;
preErrorSymbol = null;
}
break;
case 2:
len = this.productions_[action[1]][1];
yyval.$ = vstack[vstack.length - len];
yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column};
if (ranges) {
yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
}
r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
if (typeof r !== "undefined") {
return r;
}
if (len) {
stack = stack.slice(0, -1 * len * 2);
vstack = vstack.slice(0, -1 * len);
lstack = lstack.slice(0, -1 * len);
}
stack.push(this.productions_[action[1]][0]);
vstack.push(yyval.$);
lstack.push(yyval._$);
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
stack.push(newState);
break;
case 3:
return true;
}
}
return true;
}
};
function stripFlags(open, close) {
return {
left: open[2] === '~',
right: close[0] === '~' || close[1] === '~'
};
}
/* Jison generated lexer */
var lexer = (function(){
var lexer = ({EOF:1,
parseError:function parseError(str, hash) {
if (this.yy.parser) {
this.yy.parser.parseError(str, hash);
} else {
throw new Error(str);
}
},
setInput:function (input) {
this._input = input;
this._more = this._less = this.done = false;
this.yylineno = this.yyleng = 0;
this.yytext = this.matched = this.match = '';
this.conditionStack = ['INITIAL'];
this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
if (this.options.ranges) this.yylloc.range = [0,0];
this.offset = 0;
return this;
},
input:function () {
var ch = this._input[0];
this.yytext += ch;
this.yyleng++;
this.offset++;
this.match += ch;
this.matched += ch;
var lines = ch.match(/(?:\r\n?|\n).*/g);
if (lines) {
this.yylineno++;
this.yylloc.last_line++;
} else {
this.yylloc.last_column++;
}
if (this.options.ranges) this.yylloc.range[1]++;
this._input = this._input.slice(1);
return ch;
},
unput:function (ch) {
var len = ch.length;
var lines = ch.split(/(?:\r\n?|\n)/g);
this._input = ch + this._input;
this.yytext = this.yytext.substr(0, this.yytext.length-len-1);
//this.yyleng -= len;
this.offset -= len;
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
this.match = this.match.substr(0, this.match.length-1);
this.matched = this.matched.substr(0, this.matched.length-1);
if (lines.length-1) this.yylineno -= lines.length-1;
var r = this.yylloc.range;
this.yylloc = {first_line: this.yylloc.first_line,
last_line: this.yylineno+1,
first_column: this.yylloc.first_column,
last_column: lines ?
(lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length:
this.yylloc.first_column - len
};
if (this.options.ranges) {
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
}
return this;
},
more:function () {
this._more = true;
return this;
},
less:function (n) {
this.unput(this.match.slice(n));
},
pastInput:function () {
var past = this.matched.substr(0, this.matched.length - this.match.length);
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
},
upcomingInput:function () {
var next = this.match;
if (next.length < 20) {
next += this._input.substr(0, 20-next.length);
}
return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
},
showPosition:function () {
var pre = this.pastInput();
var c = new Array(pre.length + 1).join("-");
return pre + this.upcomingInput() + "\n" + c+"^";
},
next:function () {
if (this.done) {
return this.EOF;
}
if (!this._input) this.done = true;
var token,
match,
tempMatch,
index,
col,
lines;
if (!this._more) {
this.yytext = '';
this.match = '';
}
var rules = this._currentRules();
for (var i=0;i < rules.length; i++) {
tempMatch = this._input.match(this.rules[rules[i]]);
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
match = tempMatch;
index = i;
if (!this.options.flex) break;
}
}
if (match) {
lines = match[0].match(/(?:\r\n?|\n).*/g);
if (lines) this.yylineno += lines.length;
this.yylloc = {first_line: this.yylloc.last_line,
last_line: this.yylineno+1,
first_column: this.yylloc.last_column,
last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length};
this.yytext += match[0];
this.match += match[0];
this.matches = match;
this.yyleng = this.yytext.length;
if (this.options.ranges) {
this.yylloc.range = [this.offset, this.offset += this.yyleng];
}
this._more = false;
this._input = this._input.slice(match[0].length);
this.matched += match[0];
token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);
if (this.done && this._input) this.done = false;
if (token) return token;
else return;
}
if (this._input === "") {
return this.EOF;
} else {
return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
{text: "", token: null, line: this.yylineno});
}
},
lex:function lex() {
var r = this.next();
if (typeof r !== 'undefined') {
return r;
} else {
return this.lex();
}
},
begin:function begin(condition) {
this.conditionStack.push(condition);
},
popState:function popState() {
return this.conditionStack.pop();
},
_currentRules:function _currentRules() {
return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
},
topState:function () {
return this.conditionStack[this.conditionStack.length-2];
},
pushState:function begin(condition) {
this.begin(condition);
}});
lexer.options = {};
lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
function strip(start, end) {
return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng-end);
}
var YYSTATE=YY_START
switch($avoiding_name_collisions) {
case 0:
if(yy_.yytext.slice(-2) === "\\\\") {
strip(0,1);
this.begin("mu");
} else if(yy_.yytext.slice(-1) === "\\") {
strip(0,1);
this.begin("emu");
} else {
this.begin("mu");
}
if(yy_.yytext) return 14;
break;
case 1:return 14;
break;
case 2:
if(yy_.yytext.slice(-1) !== "\\") this.popState();
if(yy_.yytext.slice(-1) === "\\") strip(0,1);
return 14;
break;
case 3:strip(0,4); this.popState(); return 15;
break;
case 4:return 25;
break;
case 5:return 16;
break;
case 6:return 20;
break;
case 7:return 19;
break;
case 8:return 19;
break;
case 9:return 23;
break;
case 10:return 22;
break;
case 11:this.popState(); this.begin('com');
break;
case 12:strip(3,5); this.popState(); return 15;
break;
case 13:return 22;
break;
case 14:return 39;
break;
case 15:return 38;
break;
case 16:return 38;
break;
case 17:return 42;
break;
case 18:/*ignore whitespace*/
break;
case 19:this.popState(); return 24;
break;
case 20:this.popState(); return 18;
break;
case 21:yy_.yytext = strip(1,2).replace(/\\"/g,'"'); return 32;
break;
case 22:yy_.yytext = strip(1,2).replace(/\\'/g,"'"); return 32;
break;
case 23:return 40;
break;
case 24:return 34;
break;
case 25:return 34;
break;
case 26:return 33;
break;
case 27:return 38;
break;
case 28:yy_.yytext = strip(1,2); return 38;
break;
case 29:return 'INVALID';
break;
case 30:return 5;
break;
}
};
lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{(~)?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s])))/,/^(?:false(?=([~}\s])))/,/^(?:-?[0-9]+(?=([~}\s])))/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.]))))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/];
lexer.conditions = {"mu":{"rules":[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[3],"inclusive":false},"INITIAL":{"rules":[0,1,30],"inclusive":true}};
return lexer;})()
parser.lexer = lexer;
function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser;
return new Parser;
})();__exports__ = handlebars;
return __exports__;
})();
// handlebars/compiler/base.js
var __module8__ = (function(__dependency1__, __dependency2__) {
"use strict";
var __exports__ = {};
var parser = __dependency1__;
var AST = __dependency2__;
__exports__.parser = parser;
function parse(input) {
// Just return if an already-compile AST was passed in.
if(input.constructor === AST.ProgramNode) { return input; }
parser.yy = AST;
return parser.parse(input);
}
__exports__.parse = parse;
return __exports__;
})(__module9__, __module7__);
// handlebars/compiler/javascript-compiler.js
var __module11__ = (function(__dependency1__) {
"use strict";
var __exports__;
var COMPILER_REVISION = __dependency1__.COMPILER_REVISION;
var REVISION_CHANGES = __dependency1__.REVISION_CHANGES;
var log = __dependency1__.log;
function Literal(value) {
this.value = value;
}
function JavaScriptCompiler() {}
JavaScriptCompiler.prototype = {
// PUBLIC API: You can override these methods in a subclass to provide
// alternative compiled forms for name lookup and buffering semantics
nameLookup: function(parent, name /* , type*/) {
var wrap,
ret;
if (parent.indexOf('depth') === 0) {
wrap = true;
}
if (/^[0-9]+$/.test(name)) {
ret = parent + "[" + name + "]";
} else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
ret = parent + "." + name;
}
else {
ret = parent + "['" + name + "']";
}
if (wrap) {
return '(' + parent + ' && ' + ret + ')';
} else {
return ret;
}
},
appendToBuffer: function(string) {
if (this.environment.isSimple) {
return "return " + string + ";";
} else {
return {
appendToBuffer: true,
content: string,
toString: function() { return "buffer += " + string + ";"; }
};
}
},
initializeBuffer: function() {
return this.quotedString("");
},
namespace: "Handlebars",
// END PUBLIC API
compile: function(environment, options, context, asObject) {
this.environment = environment;
this.options = options || {};
log('debug', this.environment.disassemble() + "\n\n");
this.name = this.environment.name;
this.isChild = !!context;
this.context = context || {
programs: [],
environments: [],
aliases: { }
};
this.preamble();
this.stackSlot = 0;
this.stackVars = [];
this.registers = { list: [] };
this.compileStack = [];
this.inlineStack = [];
this.compileChildren(environment, options);
var opcodes = environment.opcodes, opcode;
this.i = 0;
for(var l=opcodes.length; this.i<l; this.i++) {
opcode = opcodes[this.i];
if(opcode.opcode === 'DECLARE') {
this[opcode.name] = opcode.value;
} else {
this[opcode.opcode].apply(this, opcode.args);
}
// Reset the stripNext flag if it was not set by this operation.
if (opcode.opcode !== this.stripNext) {
this.stripNext = false;
}
}
// Flush any trailing content that might be pending.
this.pushSource('');
return this.createFunctionContext(asObject);
},
preamble: function() {
var out = [];
if (!this.isChild) {
var namespace = this.namespace;
var copies = "helpers = this.merge(helpers, " + namespace + ".helpers);";
if (this.environment.usePartial) { copies = copies + " partials = this.merge(partials, " + namespace + ".partials);"; }
if (this.options.data) { copies = copies + " data = data || {};"; }
out.push(copies);
} else {
out.push('');
}
if (!this.environment.isSimple) {
out.push(", buffer = " + this.initializeBuffer());
} else {
out.push("");
}
// track the last context pushed into place to allow skipping the
// getContext opcode when it would be a noop
this.lastContext = 0;
this.source = out;
},
createFunctionContext: function(asObject) {
var locals = this.stackVars.concat(this.registers.list);
if(locals.length > 0) {
this.source[1] = this.source[1] + ", " + locals.join(", ");
}
// Generate minimizer alias mappings
if (!this.isChild) {
for (var alias in this.context.aliases) {
if (this.context.aliases.hasOwnProperty(alias)) {
this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
}
}
}
if (this.source[1]) {
this.source[1] = "var " + this.source[1].substring(2) + ";";
}
// Merge children
if (!this.isChild) {
this.source[1] += '\n' + this.context.programs.join('\n') + '\n';
}
if (!this.environment.isSimple) {
this.pushSource("return buffer;");
}
var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"];
for(var i=0, l=this.environment.depths.list.length; i<l; i++) {
params.push("depth" + this.environment.depths.list[i]);
}
// Perform a second pass over the output to merge content when possible
var source = this.mergeSource();
if (!this.isChild) {
var revision = COMPILER_REVISION,
versions = REVISION_CHANGES[revision];
source = "this.compilerInfo = ["+revision+",'"+versions+"'];\n"+source;
}
if (asObject) {
params.push(source);
return Function.apply(this, params);
} else {
var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' + source + '}';
log('debug', functionSource + "\n\n");
return functionSource;
}
},
mergeSource: function() {
// WARN: We are not handling the case where buffer is still populated as the source should
// not have buffer append operations as their final action.
var source = '',
buffer;
for (var i = 0, len = this.source.length; i < len; i++) {
var line = this.source[i];
if (line.appendToBuffer) {
if (buffer) {
buffer = buffer + '\n + ' + line.content;
} else {
buffer = line.content;
}
} else {
if (buffer) {
source += 'buffer += ' + buffer + ';\n ';
buffer = undefined;
}
source += line + '\n ';
}
}
return source;
},
// [blockValue]
//
// On stack, before: hash, inverse, program, value
// On stack, after: return value of blockHelperMissing
//
// The purpose of this opcode is to take a block of the form
// `{{#foo}}...{{/foo}}`, resolve the value of `foo`, and
// replace it on the stack with the result of properly
// invoking blockHelperMissing.
blockValue: function() {
this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
var params = ["depth0"];
this.setupParams(0, params);
this.replaceStack(function(current) {
params.splice(1, 0, current);
return "blockHelperMissing.call(" + params.join(", ") + ")";
});
},
// [ambiguousBlockValue]
//
// On stack, before: hash, inverse, program, value
// Compiler value, before: lastHelper=value of last found helper, if any
// On stack, after, if no lastHelper: same as [blockValue]
// On stack, after, if lastHelper: value
ambiguousBlockValue: function() {
this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
var params = ["depth0"];
this.setupParams(0, params);
var current = this.topStack();
params.splice(1, 0, current);
// Use the options value generated from the invocation
params[params.length-1] = 'options';
this.pushSource("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }");
},
// [appendContent]
//
// On stack, before: ...
// On stack, after: ...
//
// Appends the string value of `content` to the current buffer
appendContent: function(content) {
if (this.pendingContent) {
content = this.pendingContent + content;
}
if (this.stripNext) {
content = content.replace(/^\s+/, '');
}
this.pendingContent = content;
},
// [strip]
//
// On stack, before: ...
// On stack, after: ...
//
// Removes any trailing whitespace from the prior content node and flags
// the next operation for stripping if it is a content node.
strip: function() {
if (this.pendingContent) {
this.pendingContent = this.pendingContent.replace(/\s+$/, '');
}
this.stripNext = 'strip';
},
// [append]
//
// On stack, before: value, ...
// On stack, after: ...
//
// Coerces `value` to a String and appends it to the current buffer.
//
// If `value` is truthy, or 0, it is coerced into a string and appended
// Otherwise, the empty string is appended
append: function() {
// Force anything that is inlined onto the stack so we don't have duplication
// when we examine local
this.flushInline();
var local = this.popStack();
this.pushSource("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
if (this.environment.isSimple) {
this.pushSource("else { " + this.appendToBuffer("''") + " }");
}
},
// [appendEscaped]
//
// On stack, before: value, ...
// On stack, after: ...
//
// Escape `value` and append it to the buffer
appendEscaped: function() {
this.context.aliases.escapeExpression = 'this.escapeExpression';
this.pushSource(this.appendToBuffer("escapeExpression(" + this.popStack() + ")"));
},
// [getContext]
//
// On stack, before: ...
// On stack, after: ...
// Compiler value, after: lastContext=depth
//
// Set the value of the `lastContext` compiler value to the depth
getContext: function(depth) {
if(this.lastContext !== depth) {
this.lastContext = depth;
}
},
// [lookupOnContext]
//
// On stack, before: ...
// On stack, after: currentContext[name], ...
//
// Looks up the value of `name` on the current context and pushes
// it onto the stack.
lookupOnContext: function(name) {
this.push(this.nameLookup('depth' + this.lastContext, name, 'context'));
},
// [pushContext]
//
// On stack, before: ...
// On stack, after: currentContext, ...
//
// Pushes the value of the current context onto the stack.
pushContext: function() {
this.pushStackLiteral('depth' + this.lastContext);
},
// [resolvePossibleLambda]
//
// On stack, before: value, ...
// On stack, after: resolved value, ...
//
// If the `value` is a lambda, replace it on the stack by
// the return value of the lambda
resolvePossibleLambda: function() {
this.context.aliases.functionType = '"function"';
this.replaceStack(function(current) {
return "typeof " + current + " === functionType ? " + current + ".apply(depth0) : " + current;
});
},
// [lookup]
//
// On stack, before: value, ...
// On stack, after: value[name], ...
//
// Replace the value on the stack with the result of looking
// up `name` on `value`
lookup: function(name) {
this.replaceStack(function(current) {
return current + " == null || " + current + " === false ? " + current + " : " + this.nameLookup(current, name, 'context');
});
},
// [lookupData]
//
// On stack, before: ...
// On stack, after: data, ...
//
// Push the data lookup operator
lookupData: function() {
this.push('data');
},
// [pushStringParam]
//
// On stack, before: ...
// On stack, after: string, currentContext, ...
//
// This opcode is designed for use in string mode, which
// provides the string value of a parameter along with its
// depth rather than resolving it immediately.
pushStringParam: function(string, type) {
this.pushStackLiteral('depth' + this.lastContext);
this.pushString(type);
if (typeof string === 'string') {
this.pushString(string);
} else {
this.pushStackLiteral(string);
}
},
emptyHash: function() {
this.pushStackLiteral('{}');
if (this.options.stringParams) {
this.register('hashTypes', '{}');
this.register('hashContexts', '{}');
}
},
pushHash: function() {
this.hash = {values: [], types: [], contexts: []};
},
popHash: function() {
var hash = this.hash;
this.hash = undefined;
if (this.options.stringParams) {
this.register('hashContexts', '{' + hash.contexts.join(',') + '}');
this.register('hashTypes', '{' + hash.types.join(',') + '}');
}
this.push('{\n ' + hash.values.join(',\n ') + '\n }');
},
// [pushString]
//
// On stack, before: ...
// On stack, after: quotedString(string), ...
//
// Push a quoted version of `string` onto the stack
pushString: function(string) {
this.pushStackLiteral(this.quotedString(string));
},
// [push]
//
// On stack, before: ...
// On stack, after: expr, ...
//
// Push an expression onto the stack
push: function(expr) {
this.inlineStack.push(expr);
return expr;
},
// [pushLiteral]
//
// On stack, before: ...
// On stack, after: value, ...
//
// Pushes a value onto the stack. This operation prevents
// the compiler from creating a temporary variable to hold
// it.
pushLiteral: function(value) {
this.pushStackLiteral(value);
},
// [pushProgram]
//
// On stack, before: ...
// On stack, after: program(guid), ...
//
// Push a program expression onto the stack. This takes
// a compile-time guid and converts it into a runtime-accessible
// expression.
pushProgram: function(guid) {
if (guid != null) {
this.pushStackLiteral(this.programExpression(guid));
} else {
this.pushStackLiteral(null);
}
},
// [invokeHelper]
//
// On stack, before: hash, inverse, program, params..., ...
// On stack, after: result of helper invocation
//
// Pops off the helper's parameters, invokes the helper,
// and pushes the helper's return value onto the stack.
//
// If the helper is not found, `helperMissing` is called.
invokeHelper: function(paramSize, name) {
this.context.aliases.helperMissing = 'helpers.helperMissing';
var helper = this.lastHelper = this.setupHelper(paramSize, name, true);
var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
this.push(helper.name + ' || ' + nonHelper);
this.replaceStack(function(name) {
return name + ' ? ' + name + '.call(' +
helper.callParams + ") " + ": helperMissing.call(" +
helper.helperMissingParams + ")";
});
},
// [invokeKnownHelper]
//
// On stack, before: hash, inverse, program, params..., ...
// On stack, after: result of helper invocation
//
// This operation is used when the helper is known to exist,
// so a `helperMissing` fallback is not required.
invokeKnownHelper: function(paramSize, name) {
var helper = this.setupHelper(paramSize, name);
this.push(helper.name + ".call(" + helper.callParams + ")");
},
// [invokeAmbiguous]
//
// On stack, before: hash, inverse, program, params..., ...
// On stack, after: result of disambiguation
//
// This operation is used when an expression like `{{foo}}`
// is provided, but we don't know at compile-time whether it
// is a helper or a path.
//
// This operation emits more code than the other options,
// and can be avoided by passing the `knownHelpers` and
// `knownHelpersOnly` flags at compile-time.
invokeAmbiguous: function(name, helperCall) {
this.context.aliases.functionType = '"function"';
this.pushStackLiteral('{}'); // Hash value
var helper = this.setupHelper(0, name, helperCall);
var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
var nextStack = this.nextStack();
this.pushSource('if (' + nextStack + ' = ' + helperName + ') { ' + nextStack + ' = ' + nextStack + '.call(' + helper.callParams + '); }');
this.pushSource('else { ' + nextStack + ' = ' + nonHelper + '; ' + nextStack + ' = typeof ' + nextStack + ' === functionType ? ' + nextStack + '.call(' + helper.callParams + ') : ' + nextStack + '; }');
},
// [invokePartial]
//
// On stack, before: context, ...
// On stack after: result of partial invocation
//
// This operation pops off a context, invokes a partial with that context,
// and pushes the result of the invocation back.
invokePartial: function(name) {
var params = [this.nameLookup('partials', name, 'partial'), "'" + name + "'", this.popStack(), "helpers", "partials"];
if (this.options.data) {
params.push("data");
}
this.context.aliases.self = "this";
this.push("self.invokePartial(" + params.join(", ") + ")");
},
// [assignToHash]
//
// On stack, before: value, hash, ...
// On stack, after: hash, ...
//
// Pops a value and hash off the stack, assigns `hash[key] = value`
// and pushes the hash back onto the stack.
assignToHash: function(key) {
var value = this.popStack(),
context,
type;
if (this.options.stringParams) {
type = this.popStack();
context = this.popStack();
}
var hash = this.hash;
if (context) {
hash.contexts.push("'" + key + "': " + context);
}
if (type) {
hash.types.push("'" + key + "': " + type);
}
hash.values.push("'" + key + "': (" + value + ")");
},
// HELPERS
compiler: JavaScriptCompiler,
compileChildren: function(environment, options) {
var children = environment.children, child, compiler;
for(var i=0, l=children.length; i<l; i++) {
child = children[i];
compiler = new this.compiler();
var index = this.matchExistingProgram(child);
if (index == null) {
this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
index = this.context.programs.length;
child.index = index;
child.name = 'program' + index;
this.context.programs[index] = compiler.compile(child, options, this.context);
this.context.environments[index] = child;
} else {
child.index = index;
child.name = 'program' + index;
}
}
},
matchExistingProgram: function(child) {
for (var i = 0, len = this.context.environments.length; i < len; i++) {
var environment = this.context.environments[i];
if (environment && environment.equals(child)) {
return i;
}
}
},
programExpression: function(guid) {
this.context.aliases.self = "this";
if(guid == null) {
return "self.noop";
}
var child = this.environment.children[guid],
depths = child.depths.list, depth;
var programParams = [child.index, child.name, "data"];
for(var i=0, l = depths.length; i<l; i++) {
depth = depths[i];
if(depth === 1) { programParams.push("depth0"); }
else { programParams.push("depth" + (depth - 1)); }
}
return (depths.length === 0 ? "self.program(" : "self.programWithDepth(") + programParams.join(", ") + ")";
},
register: function(name, val) {
this.useRegister(name);
this.pushSource(name + " = " + val + ";");
},
useRegister: function(name) {
if(!this.registers[name]) {
this.registers[name] = true;
this.registers.list.push(name);
}
},
pushStackLiteral: function(item) {
return this.push(new Literal(item));
},
pushSource: function(source) {
if (this.pendingContent) {
this.source.push(this.appendToBuffer(this.quotedString(this.pendingContent)));
this.pendingContent = undefined;
}
if (source) {
this.source.push(source);
}
},
pushStack: function(item) {
this.flushInline();
var stack = this.incrStack();
if (item) {
this.pushSource(stack + " = " + item + ";");
}
this.compileStack.push(stack);
return stack;
},
replaceStack: function(callback) {
var prefix = '',
inline = this.isInline(),
stack;
// If we are currently inline then we want to merge the inline statement into the
// replacement statement via ','
if (inline) {
var top = this.popStack(true);
if (top instanceof Literal) {
// Literals do not need to be inlined
stack = top.value;
} else {
// Get or create the current stack name for use by the inline
var name = this.stackSlot ? this.topStackName() : this.incrStack();
prefix = '(' + this.push(name) + ' = ' + top + '),';
stack = this.topStack();
}
} else {
stack = this.topStack();
}
var item = callback.call(this, stack);
if (inline) {
if (this.inlineStack.length || this.compileStack.length) {
this.popStack();
}
this.push('(' + prefix + item + ')');
} else {
// Prevent modification of the context depth variable. Through replaceStack
if (!/^stack/.test(stack)) {
stack = this.nextStack();
}
this.pushSource(stack + " = (" + prefix + item + ");");
}
return stack;
},
nextStack: function() {
return this.pushStack();
},
incrStack: function() {
this.stackSlot++;
if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); }
return this.topStackName();
},
topStackName: function() {
return "stack" + this.stackSlot;
},
flushInline: function() {
var inlineStack = this.inlineStack;
if (inlineStack.length) {
this.inlineStack = [];
for (var i = 0, len = inlineStack.length; i < len; i++) {
var entry = inlineStack[i];
if (entry instanceof Literal) {
this.compileStack.push(entry);
} else {
this.pushStack(entry);
}
}
}
},
isInline: function() {
return this.inlineStack.length;
},
popStack: function(wrapped) {
var inline = this.isInline(),
item = (inline ? this.inlineStack : this.compileStack).pop();
if (!wrapped && (item instanceof Literal)) {
return item.value;
} else {
if (!inline) {
this.stackSlot--;
}
return item;
}
},
topStack: function(wrapped) {
var stack = (this.isInline() ? this.inlineStack : this.compileStack),
item = stack[stack.length - 1];
if (!wrapped && (item instanceof Literal)) {
return item.value;
} else {
return item;
}
},
quotedString: function(str) {
return '"' + str
.replace(/\\/g, '\\\\')
.replace(/"/g, '\\"')
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r')
.replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4
.replace(/\u2029/g, '\\u2029') + '"';
},
setupHelper: function(paramSize, name, missingParams) {
var params = [];
this.setupParams(paramSize, params, missingParams);
var foundHelper = this.nameLookup('helpers', name, 'helper');
return {
params: params,
name: foundHelper,
callParams: ["depth0"].concat(params).join(", "),
helperMissingParams: missingParams && ["depth0", this.quotedString(name)].concat(params).join(", ")
};
},
// the params and contexts arguments are passed in arrays
// to fill in
setupParams: function(paramSize, params, useRegister) {
var options = [], contexts = [], types = [], param, inverse, program;
options.push("hash:" + this.popStack());
inverse = this.popStack();
program = this.popStack();
// Avoid setting fn and inverse if neither are set. This allows
// helpers to do a check for `if (options.fn)`
if (program || inverse) {
if (!program) {
this.context.aliases.self = "this";
program = "self.noop";
}
if (!inverse) {
this.context.aliases.self = "this";
inverse = "self.noop";
}
options.push("inverse:" + inverse);
options.push("fn:" + program);
}
for(var i=0; i<paramSize; i++) {
param = this.popStack();
params.push(param);
if(this.options.stringParams) {
types.push(this.popStack());
contexts.push(this.popStack());
}
}
if (this.options.stringParams) {
options.push("contexts:[" + contexts.join(",") + "]");
options.push("types:[" + types.join(",") + "]");
options.push("hashContexts:hashContexts");
options.push("hashTypes:hashTypes");
}
if(this.options.data) {
options.push("data:data");
}
options = "{" + options.join(",") + "}";
if (useRegister) {
this.register('options', options);
params.push('options');
} else {
params.push(options);
}
return params.join(", ");
}
};
var reservedWords = (
"break else new var" +
" case finally return void" +
" catch for switch while" +
" continue function this with" +
" default if throw" +
" delete in try" +
" do instanceof typeof" +
" abstract enum int short" +
" boolean export interface static" +
" byte extends long super" +
" char final native synchronized" +
" class float package throws" +
" const goto private transient" +
" debugger implements protected volatile" +
" double import public let yield"
).split(" ");
var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
for(var i=0, l=reservedWords.length; i<l; i++) {
compilerWords[reservedWords[i]] = true;
}
JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {
if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)) {
return true;
}
return false;
};
__exports__ = JavaScriptCompiler;
return __exports__;
})(__module2__);
// handlebars/compiler/compiler.js
var __module10__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__) {
"use strict";
var __exports__ = {};
var Exception = __dependency1__;
var parse = __dependency2__.parse;
var JavaScriptCompiler = __dependency3__;
var AST = __dependency4__;
function Compiler() {}
__exports__.Compiler = Compiler;// the foundHelper register will disambiguate helper lookup from finding a
// function in a context. This is necessary for mustache compatibility, which
// requires that context functions in blocks are evaluated by blockHelperMissing,
// and then proceed as if the resulting value was provided to blockHelperMissing.
Compiler.prototype = {
compiler: Compiler,
disassemble: function() {
var opcodes = this.opcodes, opcode, out = [], params, param;
for (var i=0, l=opcodes.length; i<l; i++) {
opcode = opcodes[i];
if (opcode.opcode === 'DECLARE') {
out.push("DECLARE " + opcode.name + "=" + opcode.value);
} else {
params = [];
for (var j=0; j<opcode.args.length; j++) {
param = opcode.args[j];
if (typeof param === "string") {
param = "\"" + param.replace("\n", "\\n") + "\"";
}
params.push(param);
}
out.push(opcode.opcode + " " + params.join(" "));
}
}
return out.join("\n");
},
equals: function(other) {
var len = this.opcodes.length;
if (other.opcodes.length !== len) {
return false;
}
for (var i = 0; i < len; i++) {
var opcode = this.opcodes[i],
otherOpcode = other.opcodes[i];
if (opcode.opcode !== otherOpcode.opcode || opcode.args.length !== otherOpcode.args.length) {
return false;
}
for (var j = 0; j < opcode.args.length; j++) {
if (opcode.args[j] !== otherOpcode.args[j]) {
return false;
}
}
}
len = this.children.length;
if (other.children.length !== len) {
return false;
}
for (i = 0; i < len; i++) {
if (!this.children[i].equals(other.children[i])) {
return false;
}
}
return true;
},
guid: 0,
compile: function(program, options) {
this.opcodes = [];
this.children = [];
this.depths = {list: []};
this.options = options;
// These changes will propagate to the other compiler components
var knownHelpers = this.options.knownHelpers;
this.options.knownHelpers = {
'helperMissing': true,
'blockHelperMissing': true,
'each': true,
'if': true,
'unless': true,
'with': true,
'log': true
};
if (knownHelpers) {
for (var name in knownHelpers) {
this.options.knownHelpers[name] = knownHelpers[name];
}
}
return this.accept(program);
},
accept: function(node) {
var strip = node.strip || {},
ret;
if (strip.left) {
this.opcode('strip');
}
ret = this[node.type](node);
if (strip.right) {
this.opcode('strip');
}
return ret;
},
program: function(program) {
var statements = program.statements;
for(var i=0, l=statements.length; i<l; i++) {
this.accept(statements[i]);
}
this.isSimple = l === 1;
this.depths.list = this.depths.list.sort(function(a, b) {
return a - b;
});
return this;
},
compileProgram: function(program) {
var result = new this.compiler().compile(program, this.options);
var guid = this.guid++, depth;
this.usePartial = this.usePartial || result.usePartial;
this.children[guid] = result;
for(var i=0, l=result.depths.list.length; i<l; i++) {
depth = result.depths.list[i];
if(depth < 2) { continue; }
else { this.addDepth(depth - 1); }
}
return guid;
},
block: function(block) {
var mustache = block.mustache,
program = block.program,
inverse = block.inverse;
if (program) {
program = this.compileProgram(program);
}
if (inverse) {
inverse = this.compileProgram(inverse);
}
var type = this.classifyMustache(mustache);
if (type === "helper") {
this.helperMustache(mustache, program, inverse);
} else if (type === "simple") {
this.simpleMustache(mustache);
// now that the simple mustache is resolved, we need to
// evaluate it by executing `blockHelperMissing`
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
this.opcode('emptyHash');
this.opcode('blockValue');
} else {
this.ambiguousMustache(mustache, program, inverse);
// now that the simple mustache is resolved, we need to
// evaluate it by executing `blockHelperMissing`
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
this.opcode('emptyHash');
this.opcode('ambiguousBlockValue');
}
this.opcode('append');
},
hash: function(hash) {
var pairs = hash.pairs, pair, val;
this.opcode('pushHash');
for(var i=0, l=pairs.length; i<l; i++) {
pair = pairs[i];
val = pair[1];
if (this.options.stringParams) {
if(val.depth) {
this.addDepth(val.depth);
}
this.opcode('getContext', val.depth || 0);
this.opcode('pushStringParam', val.stringModeValue, val.type);
} else {
this.accept(val);
}
this.opcode('assignToHash', pair[0]);
}
this.opcode('popHash');
},
partial: function(partial) {
var partialName = partial.partialName;
this.usePartial = true;
if(partial.context) {
this.ID(partial.context);
} else {
this.opcode('push', 'depth0');
}
this.opcode('invokePartial', partialName.name);
this.opcode('append');
},
content: function(content) {
this.opcode('appendContent', content.string);
},
mustache: function(mustache) {
var options = this.options;
var type = this.classifyMustache(mustache);
if (type === "simple") {
this.simpleMustache(mustache);
} else if (type === "helper") {
this.helperMustache(mustache);
} else {
this.ambiguousMustache(mustache);
}
if(mustache.escaped && !options.noEscape) {
this.opcode('appendEscaped');
} else {
this.opcode('append');
}
},
ambiguousMustache: function(mustache, program, inverse) {
var id = mustache.id,
name = id.parts[0],
isBlock = program != null || inverse != null;
this.opcode('getContext', id.depth);
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
this.opcode('invokeAmbiguous', name, isBlock);
},
simpleMustache: function(mustache) {
var id = mustache.id;
if (id.type === 'DATA') {
this.DATA(id);
} else if (id.parts.length) {
this.ID(id);
} else {
// Simplified ID for `this`
this.addDepth(id.depth);
this.opcode('getContext', id.depth);
this.opcode('pushContext');
}
this.opcode('resolvePossibleLambda');
},
helperMustache: function(mustache, program, inverse) {
var params = this.setupFullMustacheParams(mustache, program, inverse),
name = mustache.id.parts[0];
if (this.options.knownHelpers[name]) {
this.opcode('invokeKnownHelper', params.length, name);
} else if (this.options.knownHelpersOnly) {
throw new Error("You specified knownHelpersOnly, but used the unknown helper " + name);
} else {
this.opcode('invokeHelper', params.length, name);
}
},
ID: function(id) {
this.addDepth(id.depth);
this.opcode('getContext', id.depth);
var name = id.parts[0];
if (!name) {
this.opcode('pushContext');
} else {
this.opcode('lookupOnContext', id.parts[0]);
}
for(var i=1, l=id.parts.length; i<l; i++) {
this.opcode('lookup', id.parts[i]);
}
},
DATA: function(data) {
this.options.data = true;
if (data.id.isScoped || data.id.depth) {
throw new Exception('Scoped data references are not supported: ' + data.original);
}
this.opcode('lookupData');
var parts = data.id.parts;
for(var i=0, l=parts.length; i<l; i++) {
this.opcode('lookup', parts[i]);
}
},
STRING: function(string) {
this.opcode('pushString', string.string);
},
INTEGER: function(integer) {
this.opcode('pushLiteral', integer.integer);
},
BOOLEAN: function(bool) {
this.opcode('pushLiteral', bool.bool);
},
comment: function() {},
// HELPERS
opcode: function(name) {
this.opcodes.push({ opcode: name, args: [].slice.call(arguments, 1) });
},
declare: function(name, value) {
this.opcodes.push({ opcode: 'DECLARE', name: name, value: value });
},
addDepth: function(depth) {
if(isNaN(depth)) { throw new Error("EWOT"); }
if(depth === 0) { return; }
if(!this.depths[depth]) {
this.depths[depth] = true;
this.depths.list.push(depth);
}
},
classifyMustache: function(mustache) {
var isHelper = mustache.isHelper;
var isEligible = mustache.eligibleHelper;
var options = this.options;
// if ambiguous, we can possibly resolve the ambiguity now
if (isEligible && !isHelper) {
var name = mustache.id.parts[0];
if (options.knownHelpers[name]) {
isHelper = true;
} else if (options.knownHelpersOnly) {
isEligible = false;
}
}
if (isHelper) { return "helper"; }
else if (isEligible) { return "ambiguous"; }
else { return "simple"; }
},
pushParams: function(params) {
var i = params.length, param;
while(i--) {
param = params[i];
if(this.options.stringParams) {
if(param.depth) {
this.addDepth(param.depth);
}
this.opcode('getContext', param.depth || 0);
this.opcode('pushStringParam', param.stringModeValue, param.type);
} else {
this[param.type](param);
}
}
},
setupMustacheParams: function(mustache) {
var params = mustache.params;
this.pushParams(params);
if(mustache.hash) {
this.hash(mustache.hash);
} else {
this.opcode('emptyHash');
}
return params;
},
// this will replace setupMustacheParams when we're done
setupFullMustacheParams: function(mustache, program, inverse) {
var params = mustache.params;
this.pushParams(params);
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
if(mustache.hash) {
this.hash(mustache.hash);
} else {
this.opcode('emptyHash');
}
return params;
}
};
function precompile(input, options) {
if (input == null || (typeof input !== 'string' && input.constructor !== AST.ProgramNode)) {
throw new Exception("You must pass a string or Handlebars AST to Handlebars.precompile. You passed " + input);
}
options = options || {};
if (!('data' in options)) {
options.data = true;
}
var ast = parse(input);
var environment = new Compiler().compile(ast, options);
return new JavaScriptCompiler().compile(environment, options);
}
__exports__.precompile = precompile;function compile(input, options, env) {
if (input == null || (typeof input !== 'string' && input.constructor !== AST.ProgramNode)) {
throw new Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input);
}
options = options || {};
if (!('data' in options)) {
options.data = true;
}
var compiled;
function compileInput() {
var ast = parse(input);
var environment = new Compiler().compile(ast, options);
var templateSpec = new JavaScriptCompiler().compile(environment, options, undefined, true);
return env.template(templateSpec);
}
// Template is only compiled on first use and cached after that point.
return function(context, options) {
if (!compiled) {
compiled = compileInput();
}
return compiled.call(this, context, options);
};
}
__exports__.compile = compile;
return __exports__;
})(__module5__, __module8__, __module11__, __module7__);
// handlebars.js
var __module0__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
"use strict";
var __exports__;
var Handlebars = __dependency1__;
// Compiler imports
var AST = __dependency2__;
var Parser = __dependency3__.parser;
var parse = __dependency3__.parse;
var Compiler = __dependency4__.Compiler;
var compile = __dependency4__.compile;
var precompile = __dependency4__.precompile;
var JavaScriptCompiler = __dependency5__;
var _create = Handlebars.create;
var create = function() {
var hb = _create();
hb.compile = function(input, options) {
return compile(input, options, hb);
};
hb.precompile = precompile;
hb.AST = AST;
hb.Compiler = Compiler;
hb.JavaScriptCompiler = JavaScriptCompiler;
hb.Parser = Parser;
hb.parse = parse;
return hb;
};
Handlebars = create();
Handlebars.create = create;
__exports__ = Handlebars;
return __exports__;
})(__module1__, __module7__, __module8__, __module10__, __module11__);
return __module0__;
})();

View File

@@ -1,270 +0,0 @@
/*
Diacritic Annotator Plugin v1.0 (https://github.com/lduarte1991/diacritic-annotator)
Copyright (C) 2014 Luis F Duarte
License: https://github.com/lduarte1991/diacritic-annotator/blob/master/LICENSE.rst
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
var _ref;
var __bind = function(fn, me){
return function(){
return fn.apply(me, arguments);
};
};
var __hasProp = {}.hasOwnProperty;
var __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;
};
Annotator.Plugin.Diacritics = (function(_super) {
__extends(Diacritics, _super);
//Options will include diacritic name, picture used, baseline
Diacritics.prototype.options = null;
Diacritics.prototype.diacriticmarks = null;
/**
* Declares all the functions and variables that the plugin will need.
* @constructor
*/
function Diacritics(element,options) {
this.pluginSubmit = __bind(this.pluginSubmit, this);
this.updateDiacritics = __bind(this.updateDiacritics, this);
this.updateViewer = __bind(this.updateViewer, this);
this.getDiacritics = __bind(this.getDiacritics, this);
this.getPos = __bind(this.getPos, this);
this.putMarkAtLocation = __bind(this.putMarkAtLocation, this);
this.updateEditorForDiacritics =
__bind(this.updateEditorForDiacritics, this);
this.options = options;
this.diacriticmarks = this.getDiacritics();
_ref = Diacritics.__super__.constructor.apply(this, arguments);
return _ref;
}
//example variables to be used to receive input in the annotator view
Diacritics.prototype.field = null;
Diacritics.prototype.input = null;
/**
* Initalizes the Plug-in for diacritic marks. It adds in the field for the mark
* and sets up listeners from the Annotator.js file to make changes as needed
*/
Diacritics.prototype.pluginInit = function() {
//Check that annotator is working
if (!Annotator.supported()) {
return;
}
var di = this.diacriticmarks;
//-- Editor
var self = this;
if(di != 'undefined'){
$.each(di,function(item){
self.field = self.annotator.editor.addField({
//options (textarea,input,select,checkbox)
type: 'checkbox',
label: Annotator._t(item),
submit: self.pluginSubmit,
});
});
//-- Viewer
this.annotator.viewer.addField({
load: this.updateViewer,
});
this.annotator.subscribe('annotationsLoaded', this.updateDiacritics);
this.annotator.subscribe('annotationUploaded', this.updateDiacritics);
this.annotator.subscribe('annotationDeleted', this.updateDiacritics);
this.annotator.subscribe('annotationUpdated', this.updateDiacritics);
this.annotator.subscribe('annotationEditorShown', this.updateEditorForDiacritics, this.field);
$(window).resize(this.updateDiacritics.bind(this));
}
return this.input = $(this.field).find(':input');
};
/**
* Adds or removes tag from checked/unchecked boxes of diacritics available
* @param field {Object} - element which holds editor
* @param annotation {Object} - object that contains annotation information from database
*/
Diacritics.prototype.pluginSubmit = function(field, annotation) {
var checkedItems = $(this.field).find(':input');
var self = this;
$.each(checkedItems, function(item){
if(typeof annotation.tags != 'undefined'){
var index = $.inArray(checkedItems[item].placeholder, annotation.tags);
if(index != -1){
annotation.tags.splice(index, 1);
var annotatorWrapper = $('.annotator-wrapper').first();
var element = annotatorWrapper.find('div.' + annotation.id);
if(!element.length){
element = annotatorWrapper.find('div.undefined');
}
element.remove();
}
if(checkedItems[item].checked === true){
annotation.tags.unshift(checkedItems[item].placeholder);
self.putMarkAtLocation(annotation, checkedItems[item].placeholder);
}
} else {
if(checkedItems[item].checked === true){
annotation.tags = [checkedItems[item].placeholder];
self.putMarkAtLocation(annotation, checkedItems[item].placeholder);
}
}
});
};
/**
* Draws the mark above a specific annotation
* @param annotation {Object} - location where mark should go
* @param mark {string}- type of mark that should go above annotation
*/
Diacritics.prototype.putMarkAtLocation = function (annotation, mark){
var loc = this.getPos(annotation.highlights[0]);
var alignment = this.diacriticmarks[mark][1];
var imgurl = this.diacriticmarks[mark][0];
var top;
switch(alignment){
case 'top':
top = (loc.y-5);
break;
case 'bottom':
top = (loc.y + loc.height-5);
break;
default:
top = loc.y;
}
$('<div></div>').addClass('mark ' + annotation.id).css({
'top': top,
'left': loc.x + (0.5 * loc.width) - 5,
'background-image': 'url(' + imgurl +')',
}).appendTo('.annotator-wrapper');
};
/**
* Gets the Diacritics from the instantiation in studio
* @returns An object with the diacritics instantiated
*/
Diacritics.prototype.getDiacritics = function(){
var diacritics = {};
var diacriticsList;
if(typeof this.options.diacritics != 'undefined'){
diacriticsList = this.options.diacritics.split(",");
$.each(diacriticsList, function(key, item){
var temp = item.split(";");
if (temp.length > 2) {
diacritics[temp[0]] = [temp[1], temp[2]];
}
});
}
return diacritics;
};
/**
* Gets the position of a specific element given the wrapper
* @param el {Object} - element you are trying to get the position of
*/
Diacritics.prototype.getPos = function(el) {
var element = $(el),
elementOffset = element.offset(),
annotatorOffset = $('.annotator-wrapper').offset();
return {
x: elementOffset.left - annotatorOffset.left,
y: elementOffset.top - annotatorOffset.top,
width: element.width(),
height: element.height()
};
};
/**
* Redraws the marks above annotations by cycling through tags
*/
Diacritics.prototype.updateDiacritics = function(){
$('.mark').remove();
var annotations = this.annotator.plugins.Store.annotations;
var self = this;
$.each(annotations, function(key, annotation){
$.each(self.diacriticmarks, function(tag){
if($.inArray(tag, annotation.tags) != -1){
self.putMarkAtLocation(annotation, tag);
}
});
});
};
/**
* Removes unnecessary field that Annotator automatically adds to popup
* @param {Object} field - the html element that represents the popup
* @param {Object} annotation - the annotation element that holds metadata
*/
Diacritics.prototype.updateViewer = function(field, annotation){
$(field).remove();
};
/**
* Function for adding Diacritic choices to the annotator popup
* @param {Object} field - the html element that represents the popup
* @param {Object} annotation - the annotation element that holds metadata
*/
Diacritics.prototype.updateEditorForDiacritics =
function(field, annotation){
// if no tags are present, no need to go through this
if (typeof annotation.tags == 'undefined'){
return;
}
var inputItems = $(this.field).find(':input');
var dictOfItems = {};
var self = this;
// add each diacritic mark to a dictionary and default to off
$.each(inputItems, function(key,item){
item.checked = false;
dictOfItems[item.placeholder] = item;
});
// match tags to diacritics and check off the ones that are true
$.each(annotation.tags, function(key,tag){
if(self.diacriticmarks[tag]){
dictOfItems[tag].checked = true;
}
});
};
return Diacritics;
})(Annotator.Plugin);

View File

@@ -1,238 +0,0 @@
var _ref,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
Annotator.Plugin.Flagging = (function(_super) {
__extends(Flagging, _super);
Flagging.prototype.options = null;
// declaration function, remember to set up submit and/or update as necessary, if you don't have
// options, delete the options line below.
function Flagging(element,options) {
this.updateViewer = __bind(this.updateViewer, this);
this.updateField = __bind(this.updateField, this);
this.submitField = __bind(this.submitField, this);
this.flagAnnotation = __bind(this.flagAnnotation, this);
this.unflagAnnotation = __bind(this.unflagAnnotation, this);
this.getTotalFlaggingTags = __bind(this.getTotalFlaggingTags, this);
this.options = options;
_ref = Flagging.__super__.constructor.apply(this, arguments);
return _ref;
}
// variables to be used to receive input in the annotator view
Flagging.prototype.field = null;
Flagging.prototype.input = null;
Flagging.prototype.hasPressed = false;
Flagging.prototype.activeAnnotation = null;
Flagging.prototype.mixedTags = null;
// this function will initialize the plug-in
Flagging.prototype.pluginInit = function() {
console.log("Flagging-pluginInit");
// Check that annotator is working
if (!Annotator.supported()) {
return;
}
// -- Editor
//creates a checkbox to remove all flags
var self = this;
this.field = this.annotator.editor.addField({
type: 'checkbox',
load: this.updateField,
// Translators: please note that this is not a literal flag, but rather a report
label: Annotator._t(gettext('Check the box to remove all flags.')),
submit: this.submitField,
});
// -- Viewer
var newview = this.annotator.viewer.addField({
load: this.updateViewer,
});
return this.input = $(this.field).find(':input');
};
/**
* Gets the total number of tags associated with the flagging tool.
* @param {Object} annotation Annotation item from Annotator.
*/
Flagging.prototype.getTotalFlaggingTags = function(annotation){
var tags = (typeof annotation.tags !== 'undefined') ? annotation.tags.slice() : [];
// Goes through and gets the number of tags that contained the keyword "flagged"
return $.grep(tags, function(tag, index){
return (tag.indexOf('flagged') !== -1);
}).length;
}
/**
* Creates a new field in the editor in order to delete the flagged tags.
* @param {HTMLElement} field The HTML element contained in the editor reserved for flagging.
* @param {Object} annotation Annotation item from Annotator.
*/
Flagging.prototype.updateField = function(field, annotation) {
// figure out whether annotation is of type image or if ova is not defined (meaning it
// it doesn't have a type yet, but it is still an image).
var user_email = (annotation.media === "image" || typeof ova === 'undefined') ?
osda.options.optionsAnnotator.permissions.user.id:
ova.options.optionsAnnotator.permissions.user.id;
// get total number of flag tags as well as save a copy of the mixed tags
var totalFlags = this.getTotalFlaggingTags(annotation);
this.mixedTags = annotation.tags;
var self = this;
// only show this field if you are an instructor and there are flags to remove
if(Catch.options.instructor_email === user_email && totalFlags > 0){
// Translators: 'totalFlags' is the number of flags solely for that annotation
var message = ngettext("Check the box to remove %(totalFlags)s flag.", "Check the box to remove %(totalFlags)s flags.", totalFlags);
$(field).find('label')[0].innerHTML = interpolate(message, {totalFlags : totalFlags}, true);
this.activeAnnotation = annotation;
// add function to change the text when the user checks the box or removes the check
$(field).find('input').change(function(evt){
if(!$(field).find('input:checkbox:checked').val()){
var count = self.getTotalFlaggingTags(self.activeAnnotation);
// Translators: 'count' is the number of flags solely for that annotation that will be removed
var message = ngettext("Check the box to remove %(count)s flag.", "Check the box to remove %(count)s flags.", count)
$(field).find('label')[0].innerHTML = interpolate(message, {count: count}, true);
} else {
$(field).find('label')[0].innerHTML = gettext("All flags have been removed. To undo, uncheck the box.");
}
});
$(field).show();
} else {
$(field).hide();
}
}
/**
* Makes last-minute changes to the annotation right before it is saved in the server.
* @param {HTMLElement} field The HTML element contained in the editor reserved for flagging.
* @param {Object} annotation Annotation item from Annotator.
*/
Flagging.prototype.submitField = function(field, annotation) {
// if the user did not check the box go back and input all of the tags.
if (!$(field).find('input:checkbox:checked').val()){
annotation.tags = this.mixedTags;
}
}
/**
* The following allows you to edit the annotation popup when the viewer has already
* hit submit and is just viewing the annotation.
* @param {HTMLElement} field The HTML element contained in the editor reserved for flagging.
* @param {Object} annotation Annotation item from Annotator.
*/
Flagging.prototype.updateViewer = function(field, annotation) {
var self = this;
this.hasPressed = false;
// perform routine to check if user has pressed the button before
var tags = typeof annotation.tags != 'undefined'?annotation.tags:[];
var user = this.annotator.plugins.Permissions.user.id;
tags.forEach(function(t){
if (t.indexOf("flagged")>=0) {
var usertest = t.replace('flagged-','');
if (usertest == user)
self.hasPressed = true;
}
});
// changes display based on check done above
var fieldControl = $(this.annotator.viewer.element.find('.annotator-controls')).parent();
if (this.hasPressed) {
// make sure to use id when searching for the item so that only one of them gets changed
var message = gettext("You have already reported this annotation.");
fieldControl.prepend('<button title="' + message + '" class="flag-icon-used" id="' + annotation.id + '">');
var flagEl = fieldControl.find('.flag-icon-used#' + annotation.id);
var self = this;
// sets function to unflag after next click
flagEl.click(function(){self.unflagAnnotation(annotation,user,flagEl,field)});
} else{
// likewise, make sure to use id when searching for the item so that only one is changed
var message = gettext("Report annotation as inappropriate or offensive.");
fieldControl.prepend('<button title="' + message + '" class="flag-icon" id="' + annotation.id + '">');
var flagEl = fieldControl.find('.flag-icon#' + annotation.id);
var self = this;
// sets function to flag after next click
flagEl.click(function(){self.flagAnnotation(annotation,user,flagEl,field)});
}
var user_email = annotation.media === "image" ?
osda.options.optionsAnnotator.permissions.user.id:
ova.options.optionsAnnotator.permissions.user.id;
var totalFlags = this.getTotalFlaggingTags(annotation);
// only show the number of times an annotation has been flagged if they are the instructors
if(Catch.options.instructor_email === user_email && totalFlags > 0){
// Translators: 'count' is the number of flags solely for that annotation
var message = ngettext("This annotation has %(count)s flag.","This annotation has %(count)s flags.", totalFlags);
$(field).append("<div class=\"flag-count\">" + interpolate(message, {count : totalFlags}, true) + "</div>");
} else {
$(field).remove(); // remove the empty div created by annotator
}
}
/**
* This function changes the visual aspects of flagging an Annotation and sends changes
* to the database backend.
*/
Flagging.prototype.flagAnnotation = function(annotation, userId, flagElement, field) {
// changes the class and title to show user's flagging action worked
flagElement.attr("class","flag-icon-used");
flagElement.attr("title", gettext("You have already reported this annotation."));
// it adds the appropriate tag with the user name to make sure it is added
if (typeof annotation.tags == 'undefined') {
annotation.tags = ['flagged-'+userId];
} else{
annotation.tags.push("flagged-"+userId);
}
// annotation gets updated and a warning is published that an annotation has been flagged
this.annotator.plugins['Store'].annotationUpdated(annotation);
this.annotator.publish("flaggedAnnotation",[field,annotation]);
// now that it is flagged, it sets the click function to unflag
flagElement.click(function(){self.unflagAnnotation(annotation,userId,flagElement,field)});
}
/**
* This function changes the visual aspects of unflagging an Annotation and sends changes
* to the database backend.
*/
Flagging.prototype.unflagAnnotation = function(annotation, userId, flagElement, field) {
// changes the class and title to show user's unflagging action worked
flagElement.attr("class", "flag-icon");
flagElement.attr("title", gettext("Report annotation as inappropriate or offensive."));
// it removes the tag that signifies flagging
annotation.tags.splice(annotation.tags.indexOf('flagged-'+userId));
// annotation gets updated without the tag and a warning is published that flagging is changed
this.annotator.plugins['Store'].annotationUpdated(annotation);
this.annotator.publish("flaggedAnnotation",[field,annotation]);
// now that it is unflagged, it sets the click function to flag
flagElement.click(function(){self.unflagAnnotation(annotation,userId,flagElement,field)});
}
return Flagging;
})(Annotator.Plugin);

View File

@@ -1,279 +0,0 @@
var _ref;
var __bind = function(fn, me) {
return function() {
return fn.apply(me, arguments);
};
};
var __hasProp = {}.hasOwnProperty;
var __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;
};
Annotator.Plugin.Grouping = (function(_super) {
__extends(Grouping, _super);
// this plugin will have a threshold option (-1 = plugin should be removed)
Grouping.prototype.options = null;
// sets up the grouping structure for the plug-in
function Grouping(element, options) {
this.pluginInit = __bind(this.pluginInit, this);
this.reloadAnnotations = __bind(this.reloadAnnotations, this);
this.groupAndColor = __bind(this.groupAndColor, this);
this.clearGrouping = __bind(this.clearGrouping, this);
this.getPos = __bind(this.getPos, this);
this.groupingButtonPressed = __bind(this.groupingButtonPressed, this);
this.options = options;
_ref = Grouping.__super__.constructor.apply(this, arguments);
return _ref;
}
// instantiation of variables to be passed around below
Grouping.prototype.unfilteredAnnotations = null;
Grouping.prototype.groupedAnnotations = null;
Grouping.prototype.groupthreshold = 0;
Grouping.prototype.useGrouping = 1;
/**
* Gets the current position relative to the annotation wrapper
* @param {HTMLElement} el Element (assumed to be within annotator-wrapper) being measured.
* @return {Object} Position of element passed in using x, y coordinates
*/
Grouping.prototype.getPos = function(el) {
// gets the offset of the element and wrapper
var off = $(el).offset();
var wrapperOff = $($('.annotator-wrapper')[0]).offset();
// do height calculations from the wrapper
return {x:off.left, y:off.top-wrapperOff.top};
}
/**
* Initializes the plugin and its attributes.
*/
Grouping.prototype.pluginInit = function() {
// Check that annotator is working
if (!Annotator.supported()) {
console.log("Annotator is not supported");
return;
}
// makes sure that every time a change is made to annotations, the grouping is redone
this.annotator.subscribe('annotationsLoaded', this.reloadAnnotations);
this.annotator.subscribe('annotationUploaded', this.reloadAnnotations);
this.annotator.subscribe('annotationDeleted', this.reloadAnnotations);
this.annotator.subscribe('annotationCreated', this.reloadAnnotations);
this.annotator.subscribe('changedTabsInCatch', this.groupingButtonPressed);
// sets up the button that toggles the grouping on or off
var newdiv = document.createElement('div');
var className = 'onOffGroupButton';
newdiv.setAttribute('class', className);
// if the item is in public then it should default to grouping being on
if (options.optionsOVA.default_tab.toLowerCase() === 'public') {
newdiv.innerHTML = "Annotation Grouping: ON";
this.useGrouping = 1;
// we wait for HighlightTags to complete before reloading annotations
this.annotator.subscribe('colorizeCompleted', this.reloadAnnotations);
} else {
newdiv.innerHTML = "Annotation Grouping: OFF";
$(newdiv).addClass('buttonOff');
this.useGrouping = 0;
}
$($('.annotator-wrapper')[0]).prepend(newdiv);
$(newdiv).click(this.groupingButtonPressed);
// makes sure that if user resizes window, the annotations are regrouped
var self = this;
$(window).resize(function() {
self.reloadAnnotations();//resize just happened, pixels changed
});
};
/**
* Helper function that removes all of the side buttons and sets background to yellow
*/
Grouping.prototype.clearGrouping = function() {
$('.groupButton').remove();
$.each(this.unfilteredAnnotations, function(val) {
if (val.highlights !== undefined){
$.each(val.highlights, function(high){
$(high).css("background-color", "inherit");
});
}
});
}
/**
* Helper function that goes through and groups together annotations on the same line
*/
Grouping.prototype.groupAndColor = function() {
annotations = this.unfilteredAnnotations;
lineAnnDict = {};
var self = this;
// for each annotation, if they have highlights, get the positions and add them
// to a dictionary based on its initial line location
annotations.forEach(function(annot) {
if (annot.highlights !== undefined) {
var loc = Math.round(self.getPos(annot.highlights[0]).y);
if (lineAnnDict[loc] === undefined) {
lineAnnDict[loc] = [annot];
return;
} else {
lineAnnDict[loc].push(annot);
return;
}
}
});
this.groupedAnnotations = null;
this.groupedAnnotations = lineAnnDict;
// Then it goes through and sets the color based on the threshold set
var self = this;
$.each(lineAnnDict, function(key, val) {
if (val.length > self.groupthreshold) {
val.forEach(function(anno){
if (anno.highlights !== undefined) {
$.each(anno.highlights, function(key, anno) {
$(anno).css("background-color", "inherit");
});
}
});
} else {
val.forEach(function(anno) {
if (anno.highlights !== undefined) {
$.each(anno.highlights, function(key, anno) {
$(anno).css("background-color", "rgba(255, 255, 10, .3)");
});
}
});
}
});
}
/**
* Helper function that clears old groupings, regroups, and adds the side buttons.
*/
Grouping.prototype.reloadAnnotations = function() {
var annotations = this.annotator.plugins['Store'].annotations;
// clear the sidebuttons
this.unfilteredAnnotations = annotations;
this.clearGrouping();
if (this.useGrouping === 0) {
return;
}
this.groupAndColor();
var self = this;
// The following creates a sidebutton that is based on line location. it will
// contain a number referring to the number of hidden annotations
$.each(this.groupedAnnotations, function(key, val) {
if (val.length > self.groupthreshold) {
var newdiv = document.createElement('div');
var className = 'groupButton';
newdiv.setAttribute('class', className);
$(newdiv).css('top', "" + key + "px");
newdiv.innerHTML = val.length;
$(newdiv).attr('data-selected', '0');
$('.annotator-wrapper')[0].appendChild(newdiv);
$(newdiv).click(function(evt){
if($(evt.srcElement).attr("data-selected") === '0') {
annotations.forEach(function(annot){
if (annot.highlights !== undefined) {
$.each(annot.highlights, function(key, ann) {
$(ann).css("background-color", "inherit");
});
}
});
self.groupedAnnotations[$(evt.srcElement).css("top").replace("px", "")].forEach(function(item) {
if (item.highlights !== undefined) {
$.each(item.highlights, function(key, ann) {
$(ann).css("background-color", "rgba(255, 255, 10, 0.3)");
});
}
});
$(evt.srcElement).attr("data-selected", '1');
} else {
annotations.forEach(function(item) {
$(item).css("background-color", "inherit");
});
self.groupAndColor();
$(evt.srcElement).attr("data-selected", '0');
}
});
}
});
var self = this;
var old = self.unfilteredAnnotations.length;
setTimeout(function() {
if (old !== self.unfilteredAnnotations.length) {
self.reloadAnnotations();
}
}, 500);
return;
};
/**
* Function activated to turn grouping on or off
*/
Grouping.prototype.groupingButtonPressed = function() {
if(this.useGrouping === 1) {
// grouping is cleared
this.useGrouping = 0;
this.clearGrouping();
// remove the grouping functions from being activated by events
this.annotator.unsubscribe('annotationsLoaded', this.reloadAnnotations);
this.annotator.unsubscribe('annotationUploaded', this.reloadAnnotations);
this.annotator.unsubscribe('annotationDeleted', this.reloadAnnotations);
this.annotator.unsubscribe('annotationCreated', this.reloadAnnotations);
// redraw button to turn grouping on/off
$(".onOffGroupButton").html("Annotation Grouping: OFF");
$(".onOffGroupButton").addClass("buttonOff");
this.annotator.plugins.Store.annotations.forEach(function(annot) {
if (annot.highlights !== undefined) {
$.each(annot.highlights, function(key, ann) {
$(ann).css("background-color", "");
});
}
});
// deals with the HighlightTags Plug-In
this.annotator.publish('externalCallToHighlightTags');
this.annotator.unsubscribe('colorizeCompleted', this.reloadAnnotations);
} else {
// runs reload/regroup annotations
this.useGrouping = 1;
this.reloadAnnotations();
// subscribe again to the events triggered by annotations
this.annotator.subscribe('annotationsLoaded', this.reloadAnnotations);
this.annotator.subscribe('annotationUploaded', this.reloadAnnotations);
this.annotator.subscribe('annotationDeleted', this.reloadAnnotations);
this.annotator.subscribe('annotationCreated', this.reloadAnnotations);
// redraw button to turn grouping on/off
$(".onOffGroupButton").html("Annotation Grouping: ON");
$(".onOffGroupButton").removeClass("buttonOff");
this.annotator.subscribe('colorizeCompleted', this.reloadAnnotations);
}
}
return Grouping;
})(Annotator.Plugin);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 647 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 668 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 567 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 370 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 B

View File

@@ -1,116 +0,0 @@
/**
* jQuery Watch Plugin
*
* @author Darcy Clarke
* @version 2.0
*
* Copyright (c) 2012 Darcy Clarke
* Dual licensed under the MIT and GPL licenses.
*
* ADDS:
*
* - $.watch()
*
* USES:
*
* - DOMAttrModified event
*
* FALLBACKS:
*
* - propertychange event
* - setTimeout() with delay
*
* EXAMPLE:
*
* $('div').watch('width height', function(){
* console.log(this.style.width, this.style.height);
* });
*
* $('div').animate({width:'100px',height:'200px'}, 500);
*
*/
(function($){
$.extend($.fn, {
/**
* Watch Method
*
* @param {String} the name of the properties to watch
* @param {Object} options to overide defaults (only 'throttle' right now)
* @param {Function} callback function to be executed when attributes change
*
* @return {jQuery Object} returns the jQuery object for chainability
*/
watch : function(props, options, callback){
// Dummmy element
var element = document.createElement('div');
/**
* Checks Support for Event
*
* @param {String} the name of the event
* @param {Element Object} the element to test support against
*
* @return {Boolean} returns result of test (true/false)
*/
var isEventSupported = function(eventName, el) {
eventName = 'on' + eventName;
var supported = (eventName in el);
if(!supported){
el.setAttribute(eventName, 'return;');
supported = typeof el[eventName] == 'function';
}
return supported;
};
// Type check options
if(typeof(options) == 'function'){
callback = options;
options = {};
}
// Type check callback
if(typeof(callback) != 'function')
callback = function(){};
// Map options over defaults
options = $.extend({}, { throttle : 10 }, options);
/**
* Checks if properties have changed
*
* @param {Element Object} the element to watch
*
*/
var check = function(el) {
var data = el.data(),
changed = false,
temp;
// Loop through properties
var length = typeof data!='undefined' && typeof data.props!='undefined'?data.props.length:0;
for(var i=0;i < length; i++){
temp = el.css(data.props[i]);
if(data.vals[i] != temp){
data.vals[i] = temp;
changed = true;
break;
}
}
// Run callback if property has changed
if(changed && data.cb)
data.cb.call(el, data);
};
return this.each(function(){
var el = $(this),
cb = function(){ check.call(this, el) },
data = { props:props.split(','), cb:callback, vals: [] };
$.each(data.props, function(i){ data.vals[i] = el.css(data.props[i]); });
el.data(data);
if(isEventSupported('DOMAttrModified', element)){
el.on('DOMAttrModified', callback);
} else if(isEventSupported('propertychange', element)){
el.on('propertychange', callback);
} else {
setInterval(cb, options.throttle);
}
});
}
});
})(jQuery);

File diff suppressed because it is too large Load Diff

View File

@@ -1,2547 +0,0 @@
/*
Open Video Annotation v1.0 (http://openvideoannotation.org/)
Copyright (C) 2014 CHS (Harvard University), Daniel Cebrian Robles and Phil Desenne
License: https://github.com/CtrHellenicStudies/OpenVideoAnnotation/blob/master/License.rst
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// ----------------Utilities---------------- //
var _ref;
var __bind = function(fn, me) {
return function() {
return fn.apply(me, arguments);
};
};
var __hasProp = {}.hasOwnProperty;
var __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;
};
var createDateFromISO8601 = function(string) {
var d, date, offset, regexp, time, _ref;
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]) * 1000);
}
if (d[14]) {
offset = (Number(d[16]) * 60) + Number(d[17]);
offset *= (_ref = d[15] === '-') != null ? _ref : {
1: -1
};
}
offset -= date.getTimezoneOffset();
time = Number(date) + (offset * 60 * 1000);
date.setTime(Number(time));
return date;
};
var Util = typeof Util != 'undefined' ? Util : {};
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
};
};
// ----------------Load videojs-Annotation Plugin---------------- //
(function () {
// -- Load Annotation plugin in videojs
function vjsAnnotation_(options){
var player = this;
// variables to know if it is ready
player.annotations = new vjsAnnotation(player, options);
// When the DOM, Range Slider and the video media is loaded
function initialVideoFinished(event) {
// -- wait for plugins -- //
var wrapper = $('.annotator-wrapper').parent()[0];
var annotator = $.data(wrapper, 'annotator');
// wait for Annotator and the Share plugin
if (typeof Annotator.Plugin["Share"] === 'function') {
if (typeof annotator.isShareLoaded != 'undefined' && annotator.isShareLoaded) {
annotator.unsubscribe('shareloaded', initialVideoFinished);
} else {
annotator.subscribe('shareloaded', initialVideoFinished);
return false;
}
}
var plugin = player.annotations;
// All components will be initialize after they have been loaded by videojs
for (var index in plugin.components) {
plugin.components[index].init_();
}
player.annotations.BigNewAn.show();
// set the position of the big buttom
plugin.setposBigNew(plugin.options.posBigNew);
if(!options.showDisplay)
plugin.hideDisplay();
if(!options.showStatistics)
plugin.hideStatistics();
// Get current instance of annotator
player.annotator = annotator;
plugin.annotator = annotator;
// get annotations
var allannotations = annotator.plugins['Store'].annotations;
plugin.refreshDisplay();
// -- Listener to Range Slider Plugin
player.rangeslider.rstb.on('mousedown', function(){plugin._onMouseDownRS(event)});
// Open the autoPlay from the API
if (player.autoPlayAPI) {
var OnePlay = function () {
player.annotations.showAnnotation(player.autoPlayAPI);
$('html, body').animate({
scrollTop: $("#" + player.id_).offset().top},
'slow');
};
if (player.techName == 'Youtube')
setTimeout(OnePlay, 100); // fix the delay playing youtube
else
OnePlay();
}
// set the number of Annotations to display
plugin.refreshDesignPanel();
// check full-screen change
player.on('fullscreenchange', function() {
if (player.isFullScreen) {
$(player.annotator.wrapper[0]).addClass('vjs-fullscreen');
} else {
$(player.annotator.wrapper[0]).removeClass('vjs-fullscreen');
}
plugin.refreshDesignPanel();
});
// loaded plugin
plugin.loaded = true;
}
player.one('loadedRangeSlider', initialVideoFinished); // Loaded RangeSlider
console.log("Loaded Annotation Plugin");
}
videojs.plugin('annotations', vjsAnnotation_);
// -- Plugin
function vjsAnnotation(player, options) {
var player = player || this;
this.player = player;
this.components = {}; // holds any custom components we add to the player
options = options || {}; // plugin options
if(!options.hasOwnProperty('posBigNew'))
options.posBigNew = 'none'; // ul = up left || ur = up right || bl = below left || br = below right || c = center
if(!options.hasOwnProperty('showDisplay'))
options.showDisplay = false;
if(!options.hasOwnProperty('showStatistics'))
options.showStatistics = false;
this.options = options;
this.init();
}
// -- Methods
vjsAnnotation.prototype = {
/* Constructor */
init: function() {
var player = this.player || {};
var controlBar = player.controlBar;
var seekBar = player.controlBar.progressControl.seekBar;
this.updatePrecision = 3;
// Components and Quick Aliases
this.BigNewAn = this.components.BigNewAnnotation = player.BigNewAnnotation;
this.AnConBut = this.components.AnContainerButtons = controlBar.AnContainerButtons;
this.ShowSt = this.components.ShowStatistics = this.AnConBut.ShowStatistics;
this.NewAn = this.components.NewAnnotation = this.AnConBut.NewAnnotation;
this.ShowAn =this.components.ShowAnnotations = this.AnConBut.ShowAnnotations;
this.BackAnDisplay = this.components.BackAnDisplay = controlBar.BackAnDisplay; // Background of the panel
this.AnDisplay = this.components.AnDisplay = controlBar.BackAnDisplay.AnDisplay; // Panel with all the annotations
this.AnStat = this.components.AnStat = controlBar.BackAnDisplay.AnStat; // Panel with statistics of the number of annotations
this.BackAnDisplayScroll = this.components.BackAnDisplayScroll = controlBar.BackAnDisplayScroll; // Back Panel with all the annotations
this.backDSBar = this.components.BackAnDisplayScrollBar = this.BackAnDisplayScroll.BackAnDisplayScrollBar; // Scroll Bar
this.backDSBarSel = this.components.ScrollBarSelector = this.backDSBar.ScrollBarSelector; // Scroll Bar Selector
this.backDSTime = this.components.BackAnDisplayScrollTime = this.BackAnDisplayScroll.BackAnDisplayScrollTime; // Back Panel with time of the annotations in the scroll
this.rsd = this.components.RangeSelectorDisplay = controlBar.BackAnDisplay.RangeSelectorDisplay; // Selection the time to display the annotations
this.rsdl = this.components.RangeSelectorLeft = this.rsd.RangeSelectorLeft;
this.rsdr = this.components.RangeSelectorRight = this.rsd.RangeSelectorRight;
this.rsdb = this.components.RangeSelectorBar = this.rsd.RangeSelectorBar;
this.rsdbl = this.components.RangeSelectorBarL = this.rsdb.RangeSelectorBarL;
this.rsdbr = this.components.RangeSelectorBarR = this.rsdb.RangeSelectorBarR;
this.rs = player.rangeslider;
// local variables
this.editing = false;
var wrapper = $('.annotator-wrapper').parent()[0];
var annotator = $.data(wrapper, 'annotator');
var self = this;
// Subscribe to Annotator changes
annotator.subscribe("annotationsLoaded", function (annotations) {
if(self.loaded)
self.refreshDisplay();
});
annotator.subscribe("annotationUpdated", function (annotation) {
if(self.loaded)
self.refreshDisplay();
});
annotator.subscribe("annotationDeleted", function (annotation) {
var annotations = annotator.plugins['Store'].annotations;
var tot = typeof annotations !== 'undefined' ? annotations.length : 0;
var attempts = 0; // max 100
// This is to watch the annotations object, to see when is deleted the annotation
var ischanged = function() {
var new_tot = annotator.plugins['Store'].annotations.length;
if (attempts < 100)
setTimeout(function(){
if (new_tot !== tot) {
if(self.loaded)
self.refreshDisplay();
} else {
attempts++;
ischanged();
}
}, 100); // wait for the change in the annotations
};
ischanged();
});
this.BigNewAn.hide(); // Hide until the video is load
},
newan: function(start, end) {
var player = this.player;
var annotator = this.annotator;
var sumPercent = 10; // percentage for the last mark
var currentTime = player.currentTime();
var lastTime = this._sumPercent(currentTime, sumPercent);
var start = typeof start !== 'undefined' ? start : currentTime;
var end = typeof end !== 'undefined' ? end : lastTime;
this._reset();
// set position RS and pause the player
player.showSlider();
player.pause();
player.setValueSlider(start, end);
// This variable is to say the editor that we want create a VideoJS annotation
annotator.editor.VideoJS = this.player.id_;
annotator.adder.show();
this._setOverRS(annotator.adder);
// Open a new annotator dialog
annotator.onAdderClick();
},
showDisplay: function() {
this._reset();
// show
this.BackAnDisplay.removeClass('disable'); // show the Container
this.BackAnDisplayScroll.removeClass('disable'); // show the scroll
// active button
this.ShowAn.addClass('active');
this.options.showDisplay =true;
},
hideDisplay: function() {
// hide
this.BackAnDisplay.addClass('disable'); // hide the Container
this.BackAnDisplayScroll.addClass('disable'); // hide the scroll
// no active button
videojs.removeClass(this.ShowAn.el_, 'active');
this.options.showDisplay =false;
},
showStatistics: function() {
this._reset();
// show
this.BackAnDisplay.removeClass('disable'); // show the Container
this.AnStat.removeClass('disable'); // show Statistics
// mode (this mode will hide the annotations to show the statistics in the container)
this.BackAnDisplay.addClass('statistics'); // mode statistics
// paint
this.AnStat.paintCanvas(); // refresh canvas
// active button
this.ShowSt.addClass('active');
this.options.showStatistics =true;
},
hideStatistics: function() {
// hide
this.BackAnDisplay.addClass('disable'); // hide the Container
this.AnStat.addClass('disable'); // hide Statistics
// remove mode statistics
this.BackAnDisplay.removeClass('statistics');
// no active button
this.ShowSt.removeClass('active');
this.options.showStatistics = false;
},
showAnnotation: function(annotation) {
var isVideo = this._isVideoJS(annotation);
if (isVideo) {
var start = annotation.rangeTime.start;
var end = annotation.rangeTime.end;
var duration = this.player.duration();
var isPoint = videojs.round(start, 3) == videojs.round(end, 3);
this._reset();
// show the range slider
this.rs.show();
// set the slider position
this.rs.setValues(start, end);
// lock the player
this.rs.lock();
// play
if (!isPoint)
this.rs.playBetween(start, end);
// fix small bar
var width = Math.min(1, Math.max(0.005, (this.rs._percent(end - start)))) * 100;
this.rs.bar.el_.style.width = width + '%';
// Add the annotation object to the bar
var bar = isPoint ? this.rs[((duration - start) / duration < 0.1) ? 'left' : 'right'].el_ : this.rs.bar.el_;
var holder = $(this.rs.left.el_).parent()[0];
$(holder).append('<span class="annotator-hl"></div>');
$(bar).appendTo( $(holder).find('.annotator-hl'));
var span = $(bar).parent()[0];
$.data(span, 'annotation', annotation); // Set the object in the span
// set the editor over the range slider
this._setOverRS(this.annotator.editor.element);
this.annotator.editor.checkOrientation();
// hide the panel
this.rs.hidePanel();
}
},
hideAnnotation: function() {
this.rs.hide();
this.rs.showPanel();
// remove the last single showed annotation
var holder = $(this.rs.left.el_).parent()[0];
var holderRight = $(this.rs.right.el_).parent()[0];
if ($(holder).find('.annotator-hl').length > 0) {
$($(holder).find('.annotator-hl')[0].children[0]).appendTo(holder);
$(holder).find('.annotator-hl').remove();
} else if ($(holderRight).find('.annotator-hl').length > 0) {
$($(holderRight).find('.annotator-hl')[0].children[0]).appendTo(holderRight);
$(holderRight).find('.annotator-hl').remove();
}
},
editAnnotation: function(annotation, editor) {
// This will be usefull when we are going to edit an annotation.
if (this._isVideoJS(annotation)) {
this.hideDisplay();
var player = this.player;
var editor = editor || this.annotator.editor;
// show the slider and set in the position
player.showSlider();
player.unlockSlider();
player.setValueSlider(annotation.rangeTime.start, annotation.rangeTime.end);
// show the time panel
player.showSliderPanel();
// set the editor over the range slider
this._setOverRS(editor.element);
editor.checkOrientation();
// set the VideoJS variable
editor.VideoJS = player.id_;
}
},
refreshDisplay: function() {
var count = 0;
var allannotations = this.annotator.plugins['Store'].annotations;
// Sort by date the Array
this._sortByDate(allannotations);
// reset the panel
$(this.AnDisplay.el_).find('span').remove(); // remove the last html items
$(this.player.el_).find('.vjs-anpanel-annotation .annotation').remove(); // remove a deleted annotation without span wrapper
for (var item in allannotations) {
var an = allannotations[item];
// check if the annotation is a video annotation
if (this._isVideoJS(an)){
var div = document.createElement('div');
var span = document.createElement('span');
var start = this.rs._percent(an.rangeTime.start) * 100;
var end = this.rs._percent(an.rangeTime.end) * 100;
var width;
span.appendChild(div);
span.className = "annotator-hl";
width = Math.min(100, Math.max(0.2, end - start));
div.className = "annotation";
div.id = count;
div.style.top = count + "em";
div.style.left = start + '%';
div.style.width = width + '%';
div.start = an.rangeTime.start;
div.end = an.rangeTime.end;
this.AnDisplay.el_.appendChild(span);
// detect point annotations
if (videojs.round(start, 0) == videojs.round(end, 0)) {
$(div).css('width', '');
$(div).addClass("point");
}
// Set the object in the div
$.data(span, 'annotation', an);
// Add the highlights to the annotation
an.highlights = $(span);
count++;
}
};
var start = this.rs._seconds(parseFloat(this.rsdl.el_.style.left) / 100);
var end = this.rs._seconds(parseFloat(this.rsdr.el_.style.left) / 100);
this.showBetween(start, end, this.rsdl.include, this.rsdr.include);
},
showBetween: function (start, end, includeLeft, includeRight) {
var duration = this.player.duration();
var start = start || 0;
var end = end || duration;
var annotationsHTML = $.makeArray($(this.player.el_).find('.vjs-anpanel-annotation .annotator-hl'));
var count = 0;
for (var index in annotationsHTML) {
var an = $.data(annotationsHTML[index], 'annotation');
var expressionLeft = includeLeft ? (an.rangeTime.end >= start) : (an.rangeTime.start >= start);
var expressionRight = includeRight ? (an.rangeTime.start <= end) : (an.rangeTime.end <= end);
if (this._isVideoJS(an) && expressionLeft && expressionRight && typeof an.highlights[0] !== 'undefined') {
var annotationHTML = an.highlights[0].children[0];
annotationHTML.style.marginTop = (-1 * parseFloat(annotationHTML.style.top) + count) + 'em';
$(an.highlights[0]).show();
count++;
} else if (this._isVideoJS(an) && typeof an.highlights[0] !== 'undefined') {
$(an.highlights[0]).hide();
an.highlights[0].children[0].style.marginTop = '';
}
}
// Set the times in the scroll time panel
this.backDSTime.setTimes();
},
setposBigNew: function(pos) {
var pos = pos || 'ul';
var el = this.player.BigNewAnnotation.el_;
videojs.removeClass(el, 'ul');
videojs.removeClass(el, 'ur');
videojs.removeClass(el, 'c');
videojs.removeClass(el, 'bl');
videojs.removeClass(el, 'br');
videojs.addClass(el, pos);
},
pressedKey: function (key) {
var player = this.player;
var rs = this.player.rs;
if (typeof key !== 'undefined' && key == 73) { // -- i key
this._reset();
// show slider
this.rs.show();
// hide other elements
this.rs._reset();
this.rs.setValue(0, player.currentTime());
this.rs.right.el_.style.visibility = 'hidden';
this.rs.tpr.el_.style.visibility = 'hidden';
this.rs.ctpr.el_.style.visibility = 'hidden';
this.rs.bar.el_.style.visibility = 'hidden';
this.lastStartbyKey = player.currentTime();
} else if (typeof key!='undefined' && key==79) { // -- o key
if (this.rs.bar.el_.style.visibility == 'hidden') { // the last action was to type the i key
var start = this.lastStartbyKey != 'undefined' ? this.lastStartbyKey:0;
this.newan(start, player.currentTime());
} else {
this.newan(player.currentTime(), player.currentTime());
}
}
},
refreshDesignPanel: function() {
var player = this.player;
var emtoPx = parseFloat($(this.backDSBar.el_).css('width'));
var playerHeight = parseFloat($(player.el_).css('height'));
var controlBarHeight = parseFloat($(player.controlBar.el_).css('height'));
var newHeight = (playerHeight - controlBarHeight) / emtoPx - 5;
this.BackAnDisplay.el_.style.height = this.backDSBar.el_.style.height = (newHeight + 'em');
this.BackAnDisplay.el_.style.top = this.backDSBar.el_.style.top = "-" + (newHeight + 3 + 'em');
this.BackAnDisplayScroll.el_.children[0].style.top = "-" + (newHeight + 5 + 'em');
this.backDSTime.el_.children[0].style.top = "-" + (newHeight + 5 + 'em');
},
_reset: function() {
// Hide all the components
this.hideDisplay();
this.hideAnnotation();
this.hideStatistics();
this.player.annotator.adder.hide();
this.player.annotator.editor.hide();
this.player.annotator.viewer.hide();
// make visible all the range slider element that maybe were hidden in pressedKey event
this.rs.right.el_.style.visibility = '';
this.rs.tpr.el_.style.visibility = '';
this.rs.ctpr.el_.style.visibility = '';
this.rs.bar.el_.style.visibility = '';
// by default the range slider must be unlocked
this.rs.unlock();
// whether there is a playing selection
this.rs.bar.suspendPlay();
// refresh the design
this.refreshDesignPanel();
},
_setOverRS: function(elem) {
var annotator = this.player.annotator;
var wrapper = $('.annotator-wrapper')[0];
var positionLeft = videojs.findPosition(this.rs.left.el_);
var positionRight = videojs.findPosition(this.rs.right.el_);
var positionAnnotator = videojs.findPosition(wrapper);
var positionAdder = {};
elem[0].style.display = 'block'; // Show the adder
if (this.player.isFullScreen) {
positionAdder.top = positionLeft.top;
positionAdder.left = positionLeft.left + (positionRight.left - positionLeft.left) / 2;
} else {
positionAdder.left = positionLeft.left + (positionRight.left - positionLeft.left) / 2 - positionAnnotator.left;
positionAdder.top = positionLeft.top - positionAnnotator.top;
}
elem.css(positionAdder);
},
_onMouseDownRS: function(event) {
event.preventDefault();
if (!this.rs.options.locked) {
videojs.on(document, "mousemove", videojs.bind(this, this._onMouseMoveRS));
videojs.on(document, "mouseup", videojs.bind(this, this._onMouseUpRS));
}
},
_onMouseMoveRS: function(event) {
var player = this.player;
var annotator = player.annotator;
var rs = player.rangeslider;
annotator.editor.element[0].style.display = 'none';
rs.show();
this._setOverRS(annotator.adder);
},
_onMouseUpRS: function(event) {
videojs.off(document, "mousemove", this._onMouseMoveRS, false);
videojs.off(document, "mouseup", this._onMouseUpRS, false);
var player = this.player;
var annotator = player.annotator;
var rs = player.rangeslider;
annotator.editor.element[0].style.display = 'block';
this._setOverRS(annotator.editor.element);
},
_sumPercent: function(seconds, percent) {
// the percentage is in %
var duration = this.player.duration();
var seconds = seconds || 0;
var percent = percent || 10;
percent = Math.min(100, Math.max(0, percent));
if (isNaN(duration)) {
return 0;
}
return Math.min(duration, Math.max(0, seconds + duration * percent / 100));
},
// Detect if we are creating or editing a video-js annotation
_EditVideoAn: function () {
var annotator = this.annotator;
var isOpenVideojs = (typeof this.player != 'undefined');
var VideoJS = annotator.editor.VideoJS;
return (isOpenVideojs && typeof VideoJS!='undefined' && VideoJS!==-1);
},
// Detect if the annotation is a video-js annotation
_isVideoJS: function (an) {
var player = this.player;
var rt = an.rangeTime;
var isOpenVideojs = (typeof this.player !== 'undefined');
var isVideo = (typeof an.media !== 'undefined' && (an.media === 'video' || an.media === 'audio'));
var isContainer = (typeof an.target !== 'undefined' && an.target.container == player.id_ );
var isNumber = (typeof rt !== 'undefined' && !isNaN(parseFloat(rt.start)) && isFinite(rt.start) && !isNaN(parseFloat(rt.end)) && isFinite(rt.end));
var isSource = false;
if (isContainer) {
// Compare without extension
var isYoutube = (isOpenVideojs && typeof this.player.techName !== 'undefined') ? (this.player.techName === 'Youtube') : false;
var targetSrc = isYoutube ? an.target.src : an.target.src.substring(0, an.target.src.lastIndexOf("."));
var playerSrc = isYoutube ? player.options_.sources[0].src : player.options_.sources[0].src.substring(0, player.options_.sources[0].src.lastIndexOf("."));
isSource = (targetSrc === playerSrc);
}
return (isOpenVideojs && isVideo && isContainer && isSource && isNumber);
},
_sortByDate: function (annotations, type) {
var type = type || 'asc'; // asc => The value [0] will be the most recent date
annotations.sort(function(a, b) {
a = new Date(typeof a.updated !== 'undefined' ? createDateFromISO8601(a.updated) : '');
b = new Date(typeof b.updated !== 'undefined' ? createDateFromISO8601(b.updated) : '');
if (type == 'asc')
return (b < a) ? -1 : ((b > a) ? 1 : 0);
else
return (a < b) ? -1 : ((a > b) ? 1 : 0);
});
}
};
// ----------------CREATE new Components for video-js---------------- //
// --Charge the new Component into videojs
videojs.ControlBar.prototype.options_.children.AnContainerButtons = {}; // Container with the css for the buttons
videojs.ControlBar.prototype.options_.children.BackAnDisplay = {}; // Range Slider Time Bar
videojs.ControlBar.prototype.options_.children.BackAnDisplayScroll = {}; // Range Slider Time Bar
videojs.options.children.BigNewAnnotation = {}; // Big Button New Annotation
// -- Player--> BigNewAnnotation
/**
* Create a New Annotation with big Button
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.BigNewAnnotation = videojs.Button.extend({
/** @constructor */
init: function(player, options) {
videojs.Button.call(this, player, options);
}
});
videojs.BigNewAnnotation.prototype.init_ = function() {
this.an = this.player_.annotations;
// Hide Button if the user has selected readOnly in the Annotator options
var opts = this.an.options.optionsAnnotator;
if (typeof opts !== 'undefined' && typeof opts.readOnly !== 'undefined' && opts.readOnly)
this.hide();
};
videojs.BigNewAnnotation.prototype.createEl = function() {
return videojs.Button.prototype.createEl.call(this, 'div', {
className: 'vjs-big-new-annotation vjs-menu-button vjs-control',
innerHTML: '<div class="vjs-big-menu-button vjs-control">A</div>',
title: 'New Annotation',
});
};
videojs.BigNewAnnotation.prototype.onClick = function() {
this.an.newan();
};
// -- Player--> ControlBar--> AnContainerButtons
/**
* Container for the button CSS
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.AnContainerButtons = videojs.Component.extend({
/** @constructor */
init: function(player, options) {
videojs.Component.call(this, player, options);
}
});
videojs.AnContainerButtons.prototype.init_ = function() {};
videojs.AnContainerButtons.prototype.options_ = {
children: {
'ShowStatistics': {},
'ShowAnnotations': {},
'NewAnnotation': {},
}
};
videojs.AnContainerButtons.prototype.createEl = function() {
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-container-button-annotation vjs-menu-button vjs-control',
});
};
// -- Player--> ControlBar--> AnContainerButtons--> ShowStatistics
/**
* Button for show/hide the chart with statistics of the annotation's number
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.ShowStatistics = videojs.Button.extend({
/** @constructor */
init: function(player, options) {
videojs.Button.call(this, player, options);
}
});
videojs.ShowStatistics.prototype.init_ = function() {
this.an = this.player_.annotations;
};
videojs.ShowStatistics.prototype.createEl = function() {
return videojs.Button.prototype.createEl.call(this, 'div', {
className: 'vjs-statistics-annotation vjs-menu-button vjs-control',
title: 'Show the Statistics',
});
};
videojs.ShowStatistics.prototype.onClick = function() {
if (!this.an.options.showStatistics) this.an.showStatistics();
else this.an.hideStatistics();
};
// -- Player--> ControlBar--> AnContainerButtons--> ShowAnnotations
/**
* Button for show/hide the annotation panel
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.ShowAnnotations = videojs.Button.extend({
/** @constructor */
init: function(player, options) {
videojs.Button.call(this, player, options);
}
});
videojs.ShowAnnotations.prototype.init_ = function() {
this.an = this.player_.annotations;
};
videojs.ShowAnnotations.prototype.createEl = function() {
return videojs.Button.prototype.createEl.call(this, 'div', {
className: 'vjs-showannotations-annotation vjs-menu-button vjs-control',
title: 'Show Annotations',
});
};
videojs.ShowAnnotations.prototype.onClick = function() {
if (!this.an.options.showDisplay) this.an.showDisplay();
else this.an.hideDisplay();
};
// -- Player--> ControlBar--> AnContainerButtons--> NewAnnotation
/**
* Create a New Annotation
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.NewAnnotation = videojs.Button.extend({
/** @constructor */
init: function(player, options) {
videojs.Button.call(this, player, options);
}
});
videojs.NewAnnotation.prototype.init_ = function() {
this.an = this.player_.annotations;
// Hide Button if the user has selected readOnly in the Annotator options
var opts = this.an.options.optionsAnnotator;
if (typeof opts !== 'undefined' && typeof opts.readOnly !== 'undefined' && opts.readOnly)
this.hide();
};
videojs.NewAnnotation.prototype.createEl = function() {
return videojs.Button.prototype.createEl.call(this, 'div', {
className: 'vjs-new-annotation vjs-menu-button vjs-control',
title: 'New Annotation',
});
};
videojs.NewAnnotation.prototype.onClick = function() {
this.an.newan();
};
// -- Player--> ControlBar--> BackAnDisplay
/**
* The background annotations panel
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.BackAnDisplay = videojs.Component.extend({
/** @constructor */
init: function(player, options) {
videojs.Component.call(this, player, options);
}
});
videojs.BackAnDisplay.prototype.init_ = function() {
this.an = this.player_.annotations
self = this;
// Fix error resizing the display panel. The scroll always went up.
$(this.el_).watch('font-size', function() {
self.an.backDSBarSel.setPosition(self.an.BackAnDisplayScroll.currentValue, false);
});
};
videojs.BackAnDisplay.prototype.options_ = {
children: {
'RangeSelectorDisplay': {},
'AnDisplay': {},
'AnStat': {},
}
};
videojs.BackAnDisplay.prototype.createEl = function() {
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-back-anpanel-annotation',
});
};
// -- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay
/**
* The selector to show the annotations in a time selection
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.RangeSelectorDisplay = videojs.Component.extend({
/** @constructor */
init: function(player, options) {
videojs.Component.call(this, player, options);
this.on('mousedown', this.onMouseDown);
}
});
videojs.RangeSelectorDisplay.prototype.init_ = function() {
this.rs = this.player_.rangeslider;
this.an = this.player_.annotations;
var duration = this.an.player.duration();
this.start = 0;
this.end = duration;
// set the selection area in the extreme position
this.setPosition(0, 0, false);
this.setPosition(1, this.rs._percent(duration), false);
};
videojs.RangeSelectorDisplay.prototype.options_ = {
children: {
'RangeSelectorLeft': {},
'RangeSelectorRight': {},
'RangeSelectorBar': {},
}
};
videojs.RangeSelectorDisplay.prototype.createEl = function(){
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-rangeselector-anpanel-annotation',
});
};
videojs.RangeSelectorDisplay.prototype.onMouseDown = function(event) {
event.preventDefault();
// videojs.blockTextSelection();
videojs.on(document, "mousemove", videojs.bind(this, this.onMouseMove));
videojs.on(document, "mouseup", videojs.bind(this, this.onMouseUp));
videojs.removeClass(this.an.rsdb.el_, 'disable');
};
videojs.RangeSelectorDisplay.prototype.onMouseUp = function(event) {
videojs.off(document, "mousemove", this.onMouseMove, false);
videojs.off(document, "mouseup", this.onMouseUp, false);
videojs.addClass(this.an.rsdb.el_, 'disable');
};
videojs.RangeSelectorDisplay.prototype.onMouseMove = function(event) {
var left = this.calculateDistance(event);
if (this.an.rsdl.pressed)
this.setPosition(0, left);
else if (this.an.rsdr.pressed)
this.setPosition(1, left);
// move the frame to the position of the arrow
this.an.player.currentTime(this.rs._seconds(left));
};
videojs.RangeSelectorDisplay.prototype.calculateDistance = function(event) {
var rstbX = this.getRSTBX();
var rstbW = this.getRSTBWidth();
var handleW = this.getWidth();
// Adjusted X and Width, so handle doesn't go outside the bar
rstbX = rstbX + (handleW / 2);
rstbW = rstbW - handleW;
// Percent that the click is through the adjusted area
return Math.max(0, Math.min(1, (event.pageX - rstbX) / rstbW));
};
videojs.RangeSelectorDisplay.prototype.getRSTBWidth = function() {
return this.el_.offsetWidth;
};
videojs.RangeSelectorDisplay.prototype.getRSTBX = function() {
return videojs.findPosition(this.el_).left;
};
videojs.RangeSelectorDisplay.prototype.getWidth = function() {
var arrow = $(this.an.rsdl.el_).find('.vjs-selector-arrow')[0];
return arrow.offsetWidth; // does not matter left or right
};
videojs.RangeSelectorDisplay.prototype.setPosition = function(index, left, changeTime) {
// index = 0 for left side, index = 1 for right side
var index = index || 0;
var changeTime = typeof changeTime !== 'undefined' ? changeTime : true;
// Check for invalid position
if(isNaN(left))
return false;
// Check index between 0 and 1
if (!(index === 0 || index === 1))
return false;
// Alias
var ObjLeft = this.an.rsdl.el_;
var ObjRight = this.an.rsdr.el_;
var Obj = this.an[index === 0 ? 'rsdl' : 'rsdr'].el_;
// Check if left arrow is over the right arrow
if ((index === 0 ? this.updateLeft(left) : this.updateRight(left))) {
if (index === 1) { // right
Obj.style.left = (left * 100) + '%';
Obj.style.width = ((1 - left) * 100) + '%';
} else { // left
Obj.style.left = (left * 100) + '%';
Obj.style.width = ((left) * 100) + '%';
}
this[index === 0 ? 'start' : 'end'] = this.rs._seconds(left);
// Fix the problem when you press the button and the two arrow are underhand
// left.zIndex = 10 and right.zIndex=20. This is always less in this case:
if (index === 0 && (left * 100) >= 90)
$(ObjLeft).find('.vjs-selector-arrow')[0].style.zIndex = 25;
else
$(ObjLeft).find('.vjs-selector-arrow')[0].style.zIndex = 10;
// -- Panel
var rsdbl = this.an.rsdbl.el_,
rsdbr = this.an.rsdbr.el_,
distance = parseFloat(ObjRight.style.left) - parseFloat(ObjLeft.style.left);
if (index === 0)
rsdbl.children[0].innerHTML = videojs.formatTime(this.rs._seconds(left));
else
rsdbr.children[0].innerHTML = videojs.formatTime(this.rs._seconds(left));
if (typeof distance !== 'undefined' && distance <= 12.5) {
if (parseFloat(ObjLeft.style.left) < 7) {
rsdbl.style.top = (-1.5) + 'em';
rsdbl.style.left = 1 + 'em';
} else {
rsdbl.style.left = (-2.5) + 'em';
rsdbl.style.top = '';
}
if (parseFloat(ObjRight.style.left) > 93) {
rsdbr.style.top = (-1.5) + 'em';
rsdbr.style.right = 1 + 'em';
} else {
rsdbr.style.right = (-2.5) + 'em';
rsdbr.style.top = '';
}
} else {
rsdbl.style.left = 1 + 'em';
rsdbr.style.right = 1 + 'em';
rsdbl.style.top = '';
rsdbr.style.top = '';
}
var start = this.rs._seconds(parseFloat(ObjLeft.style.left) / 100);
var end = this.rs._seconds(parseFloat(ObjRight.style.left) / 100);
if (changeTime)
this.an.showBetween(start, end, this.an.rsdl.include, this.an.rsdr.include);
}
return true;
};
videojs.RangeSelectorDisplay.prototype.updateLeft = function(left) {
var rightVal = this.an.rsdr.el_.style.left !== '' ? this.an.rsdr.el_.style.left : 100;
var right = parseFloat(rightVal) / 100;
var bar = this.an.rsdb.el_;
var width = videojs.round((right - left), this.an.updatePrecision); // round necessary for not get 0.6e-7 for example that it's not able for the html css width
if(left <= (right+0.00001)) {
bar.style.left = (left * 100) + '%';
bar.style.width = (width * 100) + '%';
return true;
}
return false;
};
videojs.RangeSelectorDisplay.prototype.updateRight = function(right) {
var leftVal = this.an.rsdl.el_.style.left !== '' ? this.an.rsdl.el_.style.left : 0;
var left = parseFloat(leftVal) / 100;
var bar = this.an.rsdb.el_;
var width = videojs.round((right - left), this.an.updatePrecision); // round necessary for not get 0.6e-7 for example that it's not able for the html css width
if((right+0.00001) >= left) {
bar.style.width = (width * 100) + '%';
bar.style.left = ((right - width) * 100) + '%';
return true;
}
return false;
};
// -- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay--> RangeSelectorLeft
/**
* Left Time selector
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.RangeSelectorLeft = videojs.Component.extend({
/** @constructor */
init: function(player, options) {
videojs.Component.call(this, player, options);
this.on('mousedown', this.onMouseDown);
this.on('dblclick', this.ondblclick);
this.pressed = false; // to know when is mousedown
this.include = true; // to know when we want to include the boundary time in the selection or not
}
});
videojs.RangeSelectorLeft.prototype.init_ = function() {
this.rs = this.player_.rangeslider;
this.an = this.player_.annotations;
videojs.addClass(this.el_, 'include');
};
videojs.RangeSelectorLeft.prototype.createEl = function() {
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-leftselector-anpanel-annotation',
innerHTML: '<div class="vjs-selector-arrow" title="Left Annotation Selector"></div><div class="vjs-leftselector-back"></div>'
});
};
videojs.RangeSelectorLeft.prototype.onMouseDown = function(event) {
event.preventDefault();
this.pressed = true;
videojs.on(document, "mouseup", videojs.bind(this, this.onMouseUp));
videojs.addClass(this.el_, 'active');
videojs.addClass(this.el_.parentNode, 'active');
};
videojs.RangeSelectorLeft.prototype.onMouseUp = function(event) {
videojs.off(document, "mouseup", this.onMouseUp, false);
videojs.removeClass(this.el_, 'active');
videojs.removeClass(this.el_.parentNode, 'active');
this.pressed = false;
};
videojs.RangeSelectorLeft.prototype.ondblclick = function(event) {
if (this.include) {
this.include = false;
videojs.removeClass(this.el_, 'include');
} else {
this.include = true;
videojs.addClass(this.el_, 'include');
}
var left = this.an.rsd.calculateDistance(event);
this.an.rsd.setPosition(0, left);
};
// -- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay--> RangeSelectorRight
/**
* Right Time selector
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.RangeSelectorRight = videojs.Component.extend({
/** @constructor */
init: function(player, options) {
videojs.Component.call(this, player, options);
this.on('mousedown', this.onMouseDown);
this.on('dblclick', this.ondblclick);
this.pressed = false; // to know when is mousedown
this.include = true; // to know when we want to include the boundary time in the selection or not
}
});
videojs.RangeSelectorRight.prototype.init_ = function() {
this.rs = this.player_.rangeslider;
this.an = this.player_.annotations;
videojs.addClass(this.el_, 'include');
};
videojs.RangeSelectorRight.prototype.createEl = function() {
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-rightselector-anpanel-annotation',
innerHTML: '<div class="vjs-selector-arrow" title="Right Annotation Selector"></div><div class="vjs-rightselector-back"></div>'
});
};
videojs.RangeSelectorRight.prototype.onMouseDown = function(event) {
event.preventDefault();
this.pressed = true;
videojs.on(document, "mouseup", videojs.bind(this, this.onMouseUp));
videojs.addClass(this.el_, 'active');
videojs.addClass(this.el_.parentNode, 'active');
};
videojs.RangeSelectorRight.prototype.onMouseUp = function(event) {
videojs.off(document, "mouseup", this.onMouseUp, false);
videojs.removeClass(this.el_, 'active');
videojs.removeClass(this.el_.parentNode, 'active');
this.pressed = false;
};
videojs.RangeSelectorRight.prototype.ondblclick = function(event) {
if (this.include){
this.include = false;
videojs.removeClass(this.el_, 'include');
}else{
this.include = true;
videojs.addClass(this.el_, 'include');
}
var left = this.an.rsd.calculateDistance(event);
this.an.rsd.setPosition(1, left);
};
// -- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay--> RangeSelectorBar
/**
* Bar to display the selected Time
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.RangeSelectorBar = videojs.Component.extend({
/** @constructor */
init: function(player, options) {
videojs.Component.call(this, player, options);
}
});
videojs.RangeSelectorBar.prototype.init_ = function() {
videojs.addClass(this.el_, 'disable');
};
videojs.RangeSelectorBar.prototype.options_ = {
children: {
'RangeSelectorBarL': {},
'RangeSelectorBarR': {},
}
};
videojs.RangeSelectorBar.prototype.createEl = function() {
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-barselector-anpanel-annotation',
});
};
// -- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay--> RangeSelectorBar--> RangeSelectorBarL
/**
* This is the left time panel for RangeSelectorBar
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.RangeSelectorBarL = videojs.Component.extend({
/** @constructor */
init: function(player, options) {
videojs.Component.call(this, player, options);
}
});
videojs.RangeSelectorBarL.prototype.init_ = function() {};
videojs.RangeSelectorBarL.prototype.createEl = function() {
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-barselector-left',
innerHTML: '<span class="vjs-time-text">00:00</span>',
});
};
// -- Player--> ControlBar--> BackAnDisplay--> RangeSelectorDisplay--> RangeSelectorBar--> RangeSelectorBarR
/**
* This is the right time panel for RangeSelectorBar
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.RangeSelectorBarR = videojs.Component.extend({
/** @constructor */
init: function(player, options) {
videojs.Component.call(this, player, options);
}
});
videojs.RangeSelectorBarR.prototype.init_ = function() {};
videojs.RangeSelectorBarR.prototype.createEl = function() {
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-barselector-right',
innerHTML: '<span class="vjs-time-text">00:00</span>'
});
};
// -- Player--> ControlBar--> BackAnDisplay--> AnDisplay
/**
* Show the annotations in a panel
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.AnDisplay = videojs.Component.extend({
/** @constructor */
init: function(player, options) {
videojs.Component.call(this, player, options);
this.on('mousedown', this.onMouseDown);
this.on('mouseover', this.onMouseOver);
}
});
videojs.AnDisplay.prototype.init_ = function() {
this.rs = this.player_.rangeslider;
this.an = this.player_.annotations;
this.transition = false;
};
videojs.AnDisplay.prototype.createEl = function() {
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-anpanel-annotation',
});
};
videojs.AnDisplay.prototype.onMouseDown = function(event) {
var elem = $(event.target).parents('.annotator-hl').andSelf();
var _self = this;
if (elem.hasClass("annotator-hl")) {
videojs.on(document, "mouseup", videojs.bind(this, this.onMouseUp));
// Clone the bar box to make the animation
var boxup = document.createElement('div');
var ElemTop = parseFloat(elem[1].style.top);
var ElemMargin = parseFloat(elem[1].style.marginTop);
var emtoPx = parseFloat($(elem[1]).css('height'));
var isPoint = $(elem[1]).hasClass("point");
boxup.className = isPoint ? "boxup-dashed-line point" : "boxup-dashed-line";
boxup.style.left = elem[1].style.left;
boxup.style.width = elem[1].style.width;
boxup.style.top = (ElemTop + ElemMargin - this.el_.scrollTop / emtoPx) + 'em';
elem[0].parentNode.parentNode.appendChild(boxup);
}
}
videojs.AnDisplay.prototype.onMouseUp = function(event) {
if (typeof this.lastelem === 'undefined')
return false;
var elem = this.lastelem;
var _self = this;
if (elem.hasClass("annotator-hl")) {
var annotation = elem.map(function() {
return $(this).data("annotation");
})[0];
var displayHeight = (-1) * parseFloat($(this.el_).parent()[0].style.top);
var emtoPx = parseFloat($(elem[1]).css('height'));
if (typeof $(elem).parent().parent().find('.boxup-dashed-line')[0] !== 'undefined') {
$(elem).parent().parent().find('.boxup-dashed-line')[0].style.top = (displayHeight - 2) + 'em';
}
this.an.player.pause();
this.transition = true;
window.setTimeout(function () {
_self.an.showAnnotation(annotation);
_self.transition = false;
_self.onCloseViewer();
}, 900);
}
videojs.off(document, "mouseup", this.onMouseUp, false);
};
videojs.AnDisplay.prototype.onMouseOver = function(event) {
if (!this.transition && !this.an.rsdl.pressed && !this.an.rsdr.pressed) {
var annotator = this.an.annotator;
var elem = $(event.target).parents('.annotator-hl').andSelf();
// if there is a opened annotation then show the new annotation mouse over
if (typeof annotator !== 'undefined' && annotator.viewer.isShown() && elem.hasClass("annotator-hl")) {
// hide the last open viewer
annotator.viewer.hide();
// get the annotation over the mouse
var annotations = elem.map(function() {
return $(this).data("annotation");
});
// show the annotation in the viewer
annotator.showViewer($.makeArray(annotations), Util.mousePosition(event, annotator.wrapper[0]));
}
// create dashed line
elem.addClass('active');
if (typeof elem !== 'undefined' && $(elem[1]).hasClass('annotation')) {
// create dashed line under the bar
var dashed = document.createElement('div');
var boxdown = document.createElement('div');
var DisplayHeight = parseFloat(this.an.BackAnDisplay.el_.style.height);
var ElemMarginTop = elem[1].style.marginTop !== '' ? parseFloat(elem[1].style.marginTop) : 0;
var ElemTop = parseFloat(elem[1].style.top) + ElemMarginTop;
var emtoPx = parseFloat($(elem[1]).css('height'));
var isPoint = $(elem[1]).hasClass("point");
dashed.className = isPoint ? 'dashed-line point' : 'dashed-line';
boxdown.className = "box-dashed-line";
dashed.style.left = boxdown.style.left = elem[1].style.left;
dashed.style.width = boxdown.style.width = isPoint ? '0' : elem[1].style.width;
dashed.style.top = ((ElemTop + 1) - this.el_.scrollTop / emtoPx) + 'em';
dashed.style.height = ((DisplayHeight - ElemTop + 2) + this.el_.scrollTop / emtoPx) + 'em'; // get the absolute value of the top to put in the height
boxdown.style.top = (DisplayHeight + 2) + 'em';
elem[0].parentNode.parentNode.appendChild(dashed);
elem[0].parentNode.parentNode.appendChild(boxdown);
$(this.player).find('.vjs-play-progress').css('z-index', 2);
$(this.player).find('.vjs-seek-handle').css('z-index', 2);
}
// store the last selected item
if (elem.hasClass("annotator-hl"))
this.lastelem = elem;
}
};
videojs.AnDisplay.prototype.onCloseViewer = function() {
if (!this.transition) {
if (typeof this.lastelem !== 'undefined')
this.lastelem.removeClass('active');
// remove dashed line
if (typeof this.lastelem !== 'undefined' && this.lastelem.hasClass("annotator-hl")) {
$(this.lastelem).parent().parent().find('.dashed-line').remove();
$(this.lastelem).parent().parent().find('.box-dashed-line').remove();
$(this.lastelem).parent().parent().find('.boxup-dashed-line').remove();
$(this.player).find('.vjs-play-progress').css('z-index', "");
$(this.player).find('.vjs-seek-handle').css('z-index', "");
}
}
};
videojs.AnDisplay.prototype.countVisibles = function() {
var AnArray = $.makeArray(this.el_.children);
// Count visible annotations in Panel
var count = 0;
for (var index in AnArray) {
var an = AnArray[index];
if (an.style.display !== 'none') {
count++;
}
}
return count;
};
// -- Player--> ControlBar--> BackAnDisplay--> AnStat
/**
* Display with a chart with the statistics of the number of Annotations
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.AnStat = videojs.Component.extend({
/** @constructor */
init: function(player, options) {
videojs.Component.call(this, player, options);
this.marginTop = 20;
this.marginBottom = 0;
}
});
videojs.AnStat.prototype.init_ = function() {
this.rs = this.player_.rangeslider;
this.an = this.player_.annotations;
this.canvas = this.el_.children[0];
};
videojs.AnStat.prototype.createEl = function() {
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-anstat-annotation',
innerHTML: '<canvas class="vjs-char-anstat-annotation">Your browser does not support the HTML5 canvas tag.</canvas>',
});
};
videojs.AnStat.prototype.paintCanvas = function() {
var ctx = this.canvas.getContext("2d");
var points = this._getPoints();
var w = this._getWeights(points);
var maxEn = this._getMaxArray(points, 'entries');
var TotAn = this.an.AnDisplay.el_.children.length;
var duration = this.an.player.duration();
// set the position of the canvas
this.canvas.style.marginTop = Math.round(this.marginTop) + 'px';
// Add the Max Concentration and Number of annotations
if($(this.canvas).parent().find('.vjs-totan-anstat-annotation').length === 0) {
$(this.canvas).parent().append('<div class="vjs-totan-anstat-annotation">');
$(this.canvas).parent().append('<div class="vjs-maxcon-anstat-annotation">');
}
var textCanvas = $(this.canvas).parent().find('.vjs-totan-anstat-annotation')[0];
textCanvas.innerHTML = TotAn + ' total annotations';
var textCanvas = $(this.canvas).parent().find('.vjs-maxcon-anstat-annotation')[0];
textCanvas.innerHTML = 'Max Annotations = ' + maxEn;
// Added dashed line function to paint
if (window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype.lineTo) {
CanvasRenderingContext2D.prototype.dashedLine = function(x1, y1, x2, y2, dashLen) {
if (dashLen === undefined) dashLen = 2;
this.beginPath();
this.moveTo(x1, y1);
var dX = x2 - x1;
var dY = y2 - y1;
var dashes = Math.floor(Math.sqrt(dX * dX + dY * dY) / dashLen);
var dashX = dX / dashes;
var dashY = dY / dashes;
var q = 0;
while (q++ < dashes) {
x1 += dashX;
y1 += dashY;
this[q % 2 == 0 ? 'moveTo' : 'lineTo'](x1, y1);
}
this[q % 2 == 0 ? 'moveTo' : 'lineTo'](x2, y2);
this.stroke();
this.closePath();
};
};
// set the canvas size
this.canvas.height = this.an.AnDisplay.el_.offsetHeight - (this.marginTop + this.marginBottom);
this.canvas.width = this.an.AnDisplay.el_.offsetWidth;
ctx.beginPath();
ctx.strokeStyle = "rgb(255, 163, 0)";
var lastSe = 0;
var lastEn = 0;
ctx.moveTo(0, maxEn * w.Y); // Move pointer to 0, 0
for (var index in points) {
var p = points[index];
var x1 = lastSe * w.X, y1 = (maxEn - lastEn) * w.Y; // Old Point
var x2 = p.second * w.X, y2 = (maxEn - p.entries) * w.Y; // New Point
// new line
ctx.lineTo(x2, y1); // move horizontally to the new point
ctx.moveTo(x2, y1); // Move pointer
ctx.lineTo(x2, y2); // move vertically to the new point height
ctx.moveTo(x2, y2); // Prepare pointer for a new instance
// new rectangle under the curve
ctx.fillStyle = "rgba(0, 0, 0, 0.5)";
ctx.fillRect(x1, y1, (x2 - x1), (maxEn * w.Y - y1));
// store the last point
lastSe = p.second;
lastEn = p.entries;
}
// set the graphic to the end of the video
ctx.lineTo(lastSe * w.X, maxEn * w.Y);
ctx.moveTo(lastSe * w.X, maxEn * w.Y);
ctx.lineTo(duration * w.X, maxEn * w.Y);
ctx.stroke();
// dashed line down
ctx.beginPath();
ctx.dashedLine(0, maxEn * w.Y, duration * w.X, maxEn * w.Y, 8);
ctx.stroke();
// dashed line top
ctx.beginPath();
ctx.dashedLine(0, 0, duration * w.X, 0, 8);
ctx.stroke();
};
videojs.AnStat.prototype._getWeights = function(points){
var weight = {};
var panel = $(this.an.AnDisplay.el_);
var maxSe = this.an.player.duration();
var maxEn = this._getMaxArray(points, 'entries');
var panelW = parseFloat(panel.css('width'));
var panelH = parseFloat(panel.css('height')) - (this.marginTop + this.marginBottom);
weight.X = maxSe != 0 ? (panelW / maxSe) : 0;
weight.Y = maxEn != 0 ? (panelH / maxEn) : 0;
return weight;
};
videojs.AnStat.prototype._getMaxArray = function(points, variable) {
var highest = 0;
var tmp;
for (var index in points) {
tmp = points[index][variable];
if (tmp > highest) highest = tmp;
}
return highest;
};
videojs.AnStat.prototype._getPoints = function() {
var points = [];
var allannotations = this.an.annotator.plugins.Store.annotations;
for (var index in allannotations) {
var an = allannotations[index];
var start, end;
if (this.an._isVideoJS(an)) {
start = an.rangeTime.start;
end = an.rangeTime.end;
// start
if (!this._isFound(points, start)) {
points.push({
second:an.rangeTime.start,
entries:this._getNumberAnnotations(start)
});
if (an.rangeTime.start == an.rangeTime.end){ // is a point
points.push({
second:an.rangeTime.end,
entries:this._getNumberAnnotations(end, true)
});
}
}
// end
if (!this._isFound(points, end)) {
points.push({
second:an.rangeTime.end,
entries:this._getNumberAnnotations(end, true)
});
}
found = false;
}
}
points.sort(function(a, b) {
return parseFloat(a.second) - parseFloat(b.second)
});
return points;
};
videojs.AnStat.prototype._isFound = function(array, elem) {
var found = false;
for (var indexA in array) {
if(typeof array[indexA].second !== 'undefined' && array[indexA].second == elem)
found = true;
}
return found;
};
videojs.AnStat.prototype._getNumberAnnotations = function(time, end) {
var num = (typeof end !== 'undefined' && end) ? -1 : 0;
var allannotations = this.an.annotator.plugins['Store'].annotations;
for (var index in allannotations) {
var an = allannotations[index];
if (this.an._isVideoJS(an)) {
if(an.rangeTime.start <= time && an.rangeTime.end >= time)
num++;
}
}
return num;
};
// -- Player--> ControlBar--> BackAnDisplayScroll
/**
* The background annotations panel
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.BackAnDisplayScroll = videojs.Component.extend({
/** @constructor */
init: function(player, options) {
videojs.Component.call(this, player, options);
this.on('mousedown', this.onMouseDown);
this.UpValue = 0.1;
this.currentValue = 0;
}
});
videojs.BackAnDisplayScroll.prototype.init_ = function() {
this.rs = this.player_.rangeslider;
this.an = this.player_.annotations;
this.mousedownID = -1;
var self = this;
var direction;
// Firefox
$(this.an.AnDisplay.el_).bind('DOMMouseScroll', function(e) {
if (e.originalEvent.detail > 0)
direction = self.UpValue;
else
direction = -self.UpValue;
self.an.backDSBarSel.setPosition(self.getPercentScroll() + direction);
return false;
});
// IE, Opera, Safari
$(this.an.AnDisplay.el_).bind('mousewheel', function(e) {
if (e.originalEvent.wheelDelta < 0)
direction = self.UpValue;
else
direction = -self.UpValue;
self.an.backDSBarSel.setPosition(self.getPercentScroll() + direction);
return false;
});
};
videojs.BackAnDisplayScroll.prototype.options_ = {
children: {
'BackAnDisplayScrollBar': {},
'BackAnDisplayScrollTime': {},
}
};
videojs.BackAnDisplayScroll.prototype.createEl = function() {
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-scroll-anpanel-annotation',
innerHTML: '<div class="vjs-up-scroll-annotation"></div><div class="vjs-down-scroll-annotation"></div>',
});
};
videojs.BackAnDisplayScroll.prototype.onMouseDown = function(event) {
var self = this;
if (event.target.className === 'vjs-scrollbar-anpanel-annotation') {
// change position with a click in the scrollbar
this.an.backDSBarSel.onMouseMove(event);
return false;
} else if (event.target.className === 'vjs-scrollbar-selector') {
// change position with scrollbar
// this event is controlled by this.an.backDSBarSel
return false;
} else {
// change position with arrows
var direction = event.target.className=='vjs-down-scroll-annotation' ? this.UpValue : -this.UpValue;
videojs.on(document, "mouseup", videojs.bind(this, this.onMouseUp));
if(parseInt(this.mousedownID, 10) === -1) { // Prevent multimple loops!
this.mousedownID = setInterval(function () {
var pos = Math.max(0, Math.min(1, self.getPercentScroll() + direction));
self.an.backDSBarSel.setPosition(pos);
}, 100);
}
}
};
videojs.BackAnDisplayScroll.prototype.onMouseUp = function(event) {
videojs.off(document, "mouseup", this.onMouseUp, false);
var self = this;
if(parseInt(this.mousedownID, 10) != -1) { // Only stop if exists
clearInterval(this.mousedownID);
self.mousedownID = -1;
}
};
videojs.BackAnDisplayScroll.prototype.getPercentScroll = function() {
var scroll = this.an.AnDisplay.el_;
var maxscroll = scroll.scrollHeight - scroll.offsetHeight;
var currentValue = scroll.scrollTop;
return Math.max(0, Math.min(1, maxscroll !== 0 ? (currentValue / maxscroll) : 0));
};
videojs.BackAnDisplayScroll.prototype.setPercentScroll = function(percent) {
var scroll = this.an.AnDisplay.el_;
var maxscroll = scroll.scrollHeight-scroll.offsetHeight;
percent = Math.max(0, Math.min(1, percent ? percent : 0));
scroll.scrollTop = Math.round(maxscroll * percent);
};
// -- Player--> ControlBar--> BackAnDisplayScroll--> BackAnDisplayScrollBar
/**
* The Scroll bar for the display
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.BackAnDisplayScrollBar = videojs.Component.extend({
/** @constructor */
init: function(player, options) {
videojs.Component.call(this, player, options);
}
});
videojs.BackAnDisplayScrollBar.prototype.init_ = function() {};
videojs.BackAnDisplayScrollBar.prototype.options_ = {
children: {
'ScrollBarSelector': {},
}
};
videojs.BackAnDisplayScrollBar.prototype.createEl = function() {
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-scrollbar-anpanel-annotation',
});
};
// -- Player--> ControlBar--> BackAnDisplayScroll--> BackAnDisplayScrollBar--> ScrollBarSelector
/**
* The Scroll bar for the display
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.ScrollBarSelector = videojs.Component.extend({
/** @constructor */
init: function(player, options) {
videojs.Component.call(this, player, options);
this.on('mousedown', this.onMouseDown);
}
});
videojs.ScrollBarSelector.prototype.init_ = function() {
this.rs = this.player_.rangeslider;
this.an = this.player_.annotations;
videojs.addClass(this.an.backDSBar.el_, 'disable');
};
videojs.ScrollBarSelector.prototype.createEl = function() {
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-scrollbar-selector',
});
};
videojs.ScrollBarSelector.prototype.onMouseDown = function(event) {
event.preventDefault();
videojs.on(document, "mousemove", videojs.bind(this, this.onMouseMove));
videojs.on(document, "mouseup", videojs.bind(this, this.onMouseUp));
}
videojs.ScrollBarSelector.prototype.onMouseUp = function(event) {
videojs.off(document, "mousemove", this.onMouseMove, false);
videojs.off(document, "mouseup", this.onMouseUp, false);
};
videojs.ScrollBarSelector.prototype.onMouseMove = function(event) {
var top = this.calculateDistance(event);
top = this.parseMaxPercent(top); // set the max value fixing the height of the handle
this.setPosition(top);
}
videojs.ScrollBarSelector.prototype.calculateDistance = function(event) {
var scrollY = this.getscrollY();
var scrollH = this.getscrollHeight();
var handleH = this.getHeight();
// Adjusted X and Width, so handle doesn't go outside the bar
scrollY = scrollY + (handleH);
scrollH = scrollH - (handleH);
// Adjusted X and Width, so handle doesn't go outside the bar
// Percent that the click is through the adjusted area
return Math.max(0, Math.min(1, (event.pageY - scrollY) / scrollH));
};
videojs.ScrollBarSelector.prototype.getscrollHeight = function() {
return this.el_.parentNode.offsetHeight;
};
videojs.ScrollBarSelector.prototype.getscrollY = function() {
return videojs.findPosition(this.el_.parentNode).top;
};
videojs.ScrollBarSelector.prototype.getHeight = function() {
return this.el_.offsetHeight;
};
videojs.ScrollBarSelector.prototype.parseMaxHeight = function(top) {
var scrollH = this.getscrollHeight();
var handleH = this.getHeight();
var percent = handleH / scrollH;
return Math.max(0, Math.min(1 - percent, top));
};
videojs.ScrollBarSelector.prototype.parseMaxPercent = function(top) {
var scrollH = this.getscrollHeight();
var handleH = this.getHeight();
var percent = handleH / scrollH;
var newTop = top;
if (top >= (1 - percent))
newTop = 1;
return newTop;
};
videojs.ScrollBarSelector.prototype.setPosition = function(top, showBar) {
var showBar = typeof showBar !== 'undefined' ? showBar : true;
// Check for invalid position
if (isNaN(top))
return false;
// Check if there is enough annotations to scroll
if (!this.isScrollable())
return false;
// Show the Scrollbar
if (showBar) {
videojs.removeClass(this.an.backDSBar.el_, 'disable')
}
// Alias
var Obj = this.el_;
var scroll = this.an.BackAnDisplayScroll;
var scrollTime = this.an.backDSTime;
Obj.style.top = (this.parseMaxHeight(top) * 100) + '%';
scroll.setPercentScroll(top);
// Set the times in the scroll time panel
scrollTime.setTimes();
// Hide the Scrollbar in 1 sec
if(showBar) {
var _self = this;
if (typeof this.Timeout !== 'undefined')
clearTimeout(this.Timeout);
this.Timeout = window.setTimeout(function () {
videojs.addClass(_self.an.backDSBar.el_, 'disable');
}, 1000);
}
// set current position
this.an.BackAnDisplayScroll.currentValue = top;
return true;
}
videojs.ScrollBarSelector.prototype.isScrollable = function() {
var scroll = this.an.AnDisplay.el_;
var emtoPx = parseFloat($(scroll).find('.annotation').css('height'));
var minTop = parseInt(scroll.offsetHeight/emtoPx);
// Count visible annotations in Panel
var count = this.an.AnDisplay.countVisibles();
return (count > minTop);
}
// -- Player--> ControlBar--> BackAnDisplayScroll--> BackAnDisplayScrollTime
videojs.BackAnDisplayScrollTime = videojs.Component.extend({
/** @constructor */
init: function(player, options) {
videojs.Component.call(this, player, options);
}
});
videojs.BackAnDisplayScrollTime.prototype.init_ = function() {
this.rs = this.player_.rangeslider;
this.an = this.player_.annotations;
};
videojs.BackAnDisplayScrollTime.prototype.createEl = function() {
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-scrolltime-anpanel-annotation',
innerHTML: '<div class="vjs-up-scrolltime-annotation"><span class="vjs-time-text"></span></div><div class="vjs-down-scrolltime-annotation"><span class="vjs-time-text"></span></div>',
});
};
videojs.BackAnDisplayScrollTime.prototype.setTimes = function() {
var AnPos = this.getAnnotationPosition();
var AnEl = this.getElements(AnPos);
var AnTimes = this.getTimes(AnEl);
if (AnTimes.top != 'Invalid Date') {
$(this.el_).find('.vjs-up-scrolltime-annotation')[0].style.visibility = '';
$(this.el_).find('.vjs-up-scrolltime-annotation span')[0].innerHTML = AnTimes.top;
} else {
$(this.el_).find('.vjs-up-scrolltime-annotation')[0].style.visibility = 'hidden';
}
if (AnTimes.bottom != 'Invalid Date') {
$(this.el_).find('.vjs-down-scrolltime-annotation')[0].style.visibility = '';
$(this.el_).find('.vjs-down-scrolltime-annotation span')[0].innerHTML = AnTimes.bottom;
} else {
$(this.el_).find('.vjs-down-scrolltime-annotation')[0].style.visibility = 'hidden';
}
};
videojs.BackAnDisplayScrollTime.prototype.getAnnotationPosition = function() {
var backDSBarSel = this.an.backDSBarSel;
var percent = backDSBarSel.parseMaxPercent(parseFloat(backDSBarSel.el_.style.top) / 100);
var scroll = this.an.AnDisplay.el_;
var maxTop = scroll.scrollHeight;
var minTop = scroll.offsetHeight;
var maxBottom = maxTop - minTop;
var minBottom = 0;
var pos = {};
percent = percent || 0;
pos.top = Math.max(minTop, Math.min(maxTop, maxBottom * percent + scroll.offsetHeight));
pos.bottom = Math.max(minBottom, Math.min(maxBottom, maxBottom * percent));
return pos;
};
videojs.BackAnDisplayScrollTime.prototype.getElements = function(AnPos) {
var AnPos = AnPos || {};
var scroll = this.an.AnDisplay.el_;
var emtoPx = parseFloat($(scroll).find('.annotation').css('height'));
var maxTop = parseInt(scroll.scrollHeight / emtoPx);
var minTop = parseInt(scroll.offsetHeight / emtoPx);
var maxBottom = (maxTop - minTop);
var minBottom = 0;
var AnEl = {};
AnEl.top = Math.max(minTop, Math.min(maxTop, parseInt(AnPos.top / emtoPx)));
AnEl.bottom = Math.max(minBottom, Math.min(maxBottom, parseInt(AnPos.bottom / emtoPx)));
return AnEl;
};
videojs.BackAnDisplayScrollTime.prototype.getTimes = function(AnEl) {
var AnEl = AnEl || {};
var AnTimes = {};
var TopEl, BottomEl, AnTop, AnBottom;
var AnArray = $.makeArray(this.an.AnDisplay.el_.children);
AnEl.top = AnEl.top || 0;
AnEl.bottom = AnEl.bottom || 0;
// Get HTML Elements
var count = 0;
var lastEl;
for (var index in AnArray) {
var an = AnArray[index];
if (an.style.display !== 'none') {
if (count == AnEl.bottom) {
TopEl = an;
} else if (count == AnEl.top) {
BottomEl = an;
}
lastEl = an;
count++;
}
}
if (typeof BottomEl === 'undefined')
BottomEl = lastEl;
// Annotation Element
AnTop = typeof TopEl !== 'undefined' ? $.data(TopEl, 'annotation') : undefined;
AnBottom = typeof BottomEl !== 'undefined' ? $.data(BottomEl, 'annotation') : undefined;
// Update of the element
AnTimes.top = (typeof AnTop !== 'undefined' && typeof AnTop.updated !== 'undefined') ? AnTop.updated : '';
AnTimes.bottom = (typeof AnBottom !=='undefined' && typeof AnBottom.updated !== 'undefined') ? AnBottom.updated : '';
// Format
AnTimes.top = new Date(AnTimes.top !== '' ? createDateFromISO8601(AnTimes.top) : '');
AnTimes.bottom = new Date(AnTimes.bottom != '' ? createDateFromISO8601(AnTimes.bottom) : '');
return AnTimes;
};
}) ();
// ----------------Plugin for Annotator to setup videojs---------------- //
Annotator.Plugin.VideoJS = (function(_super) {
__extends(VideoJS, _super);
// constructor
function VideoJS() {
this.pluginSubmit = __bind(this.pluginSubmit, this);
_ref = VideoJS.__super__.constructor.apply(this, arguments);
this.__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;
};
return _ref;
};
VideoJS.prototype.field = null;
VideoJS.prototype.input = null;
VideoJS.prototype.pluginInit = function() {
console.log("VideoJS-pluginInit");
// Check that annotator is working
if (!Annotator.supported()) {
return;
}
// -- Editor
this.field = this.annotator.editor.addField({
id: 'vjs-input-rangeTime-annotations',
type: 'input', // options (textarea, input, select, checkbox)
submit: this.pluginSubmit,
EditVideoAn: this.EditVideoAn
});
// Modify the element created with annotator to be an invisible span
var select = '<li><span id="vjs-input-rangeTime-annotations"></span></li>';
var newfield = Annotator.$(select);
Annotator.$(this.field).replaceWith(newfield);
this.field = newfield[0];
// -- Listener for Open Video Annotator
this.initListeners();
return this.input = $(this.field).find(':input');
};
// New JSON for the database
VideoJS.prototype.pluginSubmit = function(field, annotation) {
console.log("Plug-pluginSubmit");
// Select the new JSON for the Object to save
if (this.EditVideoAn()) {
var annotator = this.annotator;
var index = annotator.editor.VideoJS;
var player = annotator.mplayer[index];
var rs = player.rangeslider;
var time = rs.getValues();
var isYoutube = (player && typeof player.techName !== 'undefined') ? (player.techName === 'Youtube') : false;
var isNew = typeof annotation.media === 'undefined';
var ext;
var type = player.options_.sources[0].type.split("/") || "";
if (isNew)
annotation.media = typeof type[0] !== 'undefined' ? type[0] : "video"; // - media (by default: video)
annotation.target = annotation.target || {}; // - target
annotation.target.container = player.id_ || ""; // - target.container
annotation.target.src = player.options_.sources[0].src || ""; // - target.src (media source)
ext = (player.options_.sources[0].src.substring(player.options_.sources[0].src.lastIndexOf("."))).toLowerCase();
ext = isYoutube ? 'Youtube' : ext; // The extension for youtube
annotation.target.ext = ext || ""; // - target.ext (extension)
annotation.rangeTime = annotation.rangeTime || {}; // - rangeTime
annotation.rangeTime.start = time.start || 0; // - rangeTime.start
annotation.rangeTime.end = time.end || 0; // - rangeTime.end
annotation.updated = new Date().toISOString(); // - updated
if (typeof annotation.created === 'undefined')
annotation.created = annotation.updated; // - created
// show the new annotation
var eventAn = isNew ? "annotationCreated" : "annotationUpdated";
function afterFinish(){
player.annotations.showAnnotation(annotation);
annotator.unsubscribe(eventAn, afterFinish);
};
annotator.subscribe(eventAn, afterFinish); // show after the annotation is in the back-end
} else {
if (typeof annotation.media === 'undefined')
annotation.media = "text"; // - media
annotation.updated = new Date().toISOString(); // - updated
if (typeof annotation.created === 'undefined')
annotation.created = annotation.updated; // - created
}
return annotation.media;
};
// ------ Methods ------ //
// Detect if we are creating or editing a video-js annotation
VideoJS.prototype.EditVideoAn = function () {
var wrapper = $('.annotator-wrapper').parent()[0];
var annotator = window.annotator = $.data(wrapper, 'annotator');
var isOpenVideojs = (typeof annotator.mplayer !== 'undefined');
var VideoJS = annotator.editor.VideoJS;
return (isOpenVideojs && typeof VideoJS !== 'undefined' && VideoJS !== -1);
};
// Detect if the annotation is a video-js annotation
VideoJS.prototype.isVideoJS = function (an) {
var wrapper = $('.annotator-wrapper').parent()[0];
var annotator = window.annotator = $.data(wrapper, 'annotator');
var rt = an.rangeTime;
var isOpenVideojs = (typeof annotator.mplayer !== 'undefined');
var isVideo = (typeof an.media !== 'undefined' && (an.media === 'video' || an.media === 'audio'));
var isNumber = (typeof rt !== 'undefined' && !isNaN(parseFloat(rt.start)) && isFinite(rt.start) && !isNaN(parseFloat(rt.end)) && isFinite(rt.end));
return (isOpenVideojs && isVideo && isNumber);
};
// Delete Video Annotation
VideoJS.prototype._deleteAnnotation = function(an) {
var target = an.target || {};
var container = target.container || {};
var player = this.annotator.mplayer[container];
var annotator = this.annotator;
var annotations = annotator.plugins.Store.annotations;
var tot = typeof annotations !== 'undefined' ? annotations.length : 0;
var attempts = 0; // max 100
// This is to watch the annotations object, to see when is deleted the annotation
var ischanged = function() {
var new_tot = annotator.plugins.Store.annotations.length;
if (attempts < 100)
setTimeout(function() {
if (new_tot !== tot) {
player.annotations.refreshDisplay(); // Reload the display of annotation
} else {
attempts++;
ischanged();
}
}, 100); // wait for the change in the annotations
};
ischanged();
player.rangeslider.hide(); // Hide Range Slider
};
// --Listeners
VideoJS.prototype.initListeners = function () {
var wrapper = $('.annotator-wrapper').parent()[0];
var annotator = $.data(wrapper, 'annotator');
var EditVideoAn = this.EditVideoAn;
var isVideoJS = this.isVideoJS;
var self = this;
// local functions
// -- Editor
function annotationEditorHidden(editor) {
if (EditVideoAn()){
var index = annotator.editor.VideoJS;
annotator.mplayer[index].rangeslider.hide(); // Hide Range Slider
annotator.an[index].refreshDisplay(); // Reload the display of annotations
}
annotator.editor.VideoJS=-1;
annotator.unsubscribe("annotationEditorHidden", annotationEditorHidden);
};
function annotationEditorShown(editor, annotation) {
for (var index in annotator.an){
annotator.an[index].editAnnotation(annotation, editor);
}
annotator.subscribe("annotationEditorHidden", annotationEditorHidden);
};
// -- Annotations
function annotationDeleted(annotation) {
if (isVideoJS(annotation))
self._deleteAnnotation(annotation);
};
// -- Viewer
function hideViewer(){
for (var index in annotator.an) {
annotator.an[index].AnDisplay.onCloseViewer();
}
annotator.viewer.unsubscribe("hide", hideViewer);
};
function annotationViewerShown(viewer, annotations) {
var separation = viewer.element.hasClass(viewer.classes.invert.y) ? 5 : -5;
var newpos = {
top: parseFloat(viewer.element[0].style.top)+separation,
left: parseFloat(viewer.element[0].style.left)
};
viewer.element.css(newpos);
// Remove the time to wait until disapear, to be more faster that annotator by default
viewer.element.find('.annotator-controls').removeClass(viewer.classes.showControls);
annotator.viewer.subscribe("hide", hideViewer);
};
// subscribe to Annotator
annotator.subscribe("annotationEditorShown", annotationEditorShown)
.subscribe("annotationDeleted", annotationDeleted)
.subscribe("annotationViewerShown", annotationViewerShown);
};
return VideoJS;
})(Annotator.Plugin);
// ----------------PUBLIC OBJECT TO CONTROL THE ANNOTATIONS---------------- //
// The name of the plugin that the user will write in the html
OpenVideoAnnotation = ("OpenVideoAnnotation" in window) ? OpenVideoAnnotation : {};
OpenVideoAnnotation.Annotator = function (element, options) {
// local variables
var $ = jQuery;
var options = options || {};
options.optionsAnnotator = options.optionsAnnotator || {};
options.optionsVideoJS = options.optionsVideoJS || {};
options.optionsRS = options.optionsRS || {};
options.optionsOVA = options.optionsOVA || {};
// if there isn't store optinos it will create a uri and limit variables for the Back-end of Annotations
if (typeof options.optionsAnnotator.store === 'undefined')
options.optionsAnnotator.store = {};
var store = options.optionsAnnotator.store;
if (typeof store.annotationData === 'undefined')
store.annotationData = {};
if (typeof store.annotationData.uri === 'undefined'){
var uri = location.protocol + '//' + location.host + location.pathname;
store.annotationData.store = {uri: uri};
}
if (typeof store.loadFromSearch === 'undefined')
store.loadFromSearch = {};
if (typeof store.loadFromSearch.uri === 'undefined')
store.loadFromSearch.uri = uri;
if (typeof store.loadFromSearch.limit === 'undefined')
store.loadFromSearch.limit = 10000;
// global variables
this.currentUser = null;
// -- Init all the classes --/
// Annotator
this.annotator = $(element).annotator(options.optionsAnnotator.annotator).data('annotator');
options.optionsOVA.optionsAnnotator = options.optionsAnnotator.annotator; // send the Annotator's options to OVA
// Video-JS
/*
mplayers -> Array with the html of all the video-js
mplayer -> Array with all the video-js that will be in the plugin
*/
var mplayers = $(element).find('div .video-js').toArray();
var mplayer = this.mplayer = {};
for (var index in mplayers) {
var id = mplayers[index].id;
var mplayer_ = videojs(mplayers[index], options.optionsVideoJS);
// solve a problem with firefox. In Firefox the src() function is loaded before charge the optionsVideoJS, and the techOrder are not loaded
if (vjs.IS_FIREFOX && typeof options.optionsVideoJS.techOrder !== 'undefined'){
mplayer_.options_.techOrder = options.optionsVideoJS.techOrder;
mplayer_.src(mplayer_.options_['sources']);
}
this.mplayer[id] = mplayer_;
}
// Video-JS
this.annotator.an = {}; // annotations video-js plugin to annotator
for (var index in this.mplayer) {
// to be their own options is necessary to extend deeply the options with all the childrens
this.mplayer[index].rangeslider($.extend(true, {}, options.optionsRS));
this.mplayer[index].annotations($.extend(true, {}, options.optionsOVA));
this.annotator.an[index]=this.mplayer[index].annotations;
}
// -- Experimental Global function for Open Video Annotator -- //
this.setCurrentUser = function (user) {
this.currentUser = user;
this.annotator.plugins["Permissions"].setUser(user);
}
// Local function to setup the keyboard listener
var focusedPlayer = this.focusedPlayer = ''; // variable to know the focused player
var lastfocusPlayer = this.lastfocusPlayer = '';
function onKeyUp(e) {
// skip the text areas
if (e.target.nodeName.toLowerCase() !== 'textarea')
mplayer[focusedPlayer].annotations.pressedKey(e.which);
};
(this._setupKeyboard = function() {
$(document).mousedown(function(e) {
focusedPlayer = '';
// Detects if a player was click
for (var index in mplayer) {
if ($(mplayer[index].el_).find(e.target).length)
focusedPlayer = mplayer[index].id_;
}
// Enter if we change the focus between player or go out of the player
if (lastfocusPlayer !== focusedPlayer) {
$(document).off("keyup", onKeyUp); // Remove the last listener
// set the key listener
if (focusedPlayer !== '')
$(document).on("keyup", onKeyUp);
}
lastfocusPlayer = focusedPlayer;
});
}) (this);
// -- Activate all the plugins -- //
// Annotator
if (typeof options.optionsAnnotator.auth !== 'undefined')
this.annotator.addPlugin('Auth', options.optionsAnnotator.auth);
if (typeof options.optionsAnnotator.permissions !== 'undefined')
this.annotator.addPlugin("Permissions", options.optionsAnnotator.permissions);
if (typeof options.optionsAnnotator.store !== 'undefined')
this.annotator.addPlugin("Store", options.optionsAnnotator.store);
if (typeof options.optionsAnnotator.diacriticMarks !== 'undefined' && typeof Annotator.Plugin["Diacritics"] === 'function')
this.annotator.addPlugin("Diacritics", options.optionsAnnotator.diacriticMarks);
if (typeof Annotator.Plugin["Geolocation"] === 'function')
this.annotator.addPlugin("Geolocation", options.optionsAnnotator.geolocation);
if (typeof Annotator.Plugin["Share"] === 'function')
this.annotator.addPlugin("Share", options.optionsAnnotator.share);
this.annotator.addPlugin("VideoJS"); // it is obligatory to have
if (typeof Annotator.Plugin["RichText"] === 'function')
this.annotator.addPlugin("RichText", options.optionsAnnotator.richText);
if (typeof Annotator.Plugin["Reply"] === 'function')
this.annotator.addPlugin("Reply");
if (typeof Annotator.Plugin["Flagging"] === 'function')
this.annotator.addPlugin("Flagging");
if (typeof options.optionsAnnotator.highlightTags !== 'undefined')
this.annotator.addPlugin("HighlightTags", options.optionsAnnotator.highlightTags);
// Will be add the player and the annotations plugin for video-js in the annotator
this.annotator.mplayer = this.mplayer;
this.annotator.editor.VideoJS = -1;
this.options = options;
return this;
}
// ----------------Local Functions for Open Video Annotator---------------- //
// --local functions
// if the annotation is a video return true
OpenVideoAnnotation.Annotator.prototype._isVideo = function(an) {
// Detect if the annotation is a Open Video Annotation
var an = an || {};
var rt = an.rangeTime;
var isVideo = (typeof an.media !== 'undefined' && (an.media === 'video' || an.media === 'audio'));
var hasContainer = (typeof an.target !== 'undefined' && typeof an.target.container !== 'undefined');
var isNumber = (typeof rt !== 'undefined' && !isNaN(parseFloat(rt.start)) && isFinite(rt.start) && !isNaN(parseFloat(rt.end)) && isFinite(rt.end));
return (isVideo && hasContainer && isNumber);
}
// if the ova has been loaded and the video is opened return true
OpenVideoAnnotation.Annotator.prototype._isloaded = function(idElem) {
return typeof this.mplayer[idElem].annotations.loaded !== 'undefined';
}
// ----------------Public Functions for Open Video Annotator---------------- //
// Create a new video annotation
OpenVideoAnnotation.Annotator.prototype.newVideoAn = function(idElem) {
var player = this.mplayer[idElem];
if (typeof player.play !== 'undefined') {
player.play();
player.one('playing', function() {
player.annotations.newan();
$('html, body').animate({
scrollTop: $("#" + player.id_).offset().top
}, 'slow');
player.pause();
});
}
};
// Show the annotation display
OpenVideoAnnotation.Annotator.prototype.showDisplay = function(idElem) {
if (this._isloaded(idElem))
return this.mplayer[idElem].annotations.showDisplay();
};
// Hide the annotation display
OpenVideoAnnotation.Annotator.prototype.hideDisplay = function(idElem) {
if (this._isloaded(idElem))
return this.mplayer[idElem].annotations.hideDisplay();
};
// Refresh the annotation display
OpenVideoAnnotation.Annotator.prototype.refreshDisplay = function(idElem) {
if (this._isloaded(idElem))
return this.mplayer[idElem].annotations.hideDisplay();
};
// Set the position of the big new annotation button
OpenVideoAnnotation.Annotator.prototype.setposBigNew = function(idElem, position) {
if (this._isloaded(idElem))
return this.mplayer[idElem].annotations.setposBigNew(position);
};
OpenVideoAnnotation.Annotator.prototype.playTarget = function (annotationId) {
var allannotations = this.annotator.plugins.Store.annotations;
var ovaId = annotationId;
var mplayer = this.mplayer;
for (var item in allannotations) {
var an = allannotations[item];
if (typeof an.id != 'undefined' && an.id == ovaId) { // this is the annotation
if (this._isVideo(an)) { // It is a video
for (var index in mplayer) {
var player = mplayer[index];
if (player.id_ == an.target.container && player.tech.options_.source.src === an.target.src){
var anFound = an;
var playFunction = function() {
// Fix problem with youtube videos in the first play. The plugin don't have this trigger
if (player.techName === 'Youtube') {
var startAPI = function() {
player.annotations.showAnnotation(anFound);
}
if (player.annotations.loaded)
startAPI();
else
player.one('loadedRangeSlider', startAPI); // show Annotations once the RangeSlider is loaded
} else {
player.annotations.showAnnotation(anFound);
}
$('html, body').animate({
scrollTop: $("#"+player.id_).offset().top
}, 'slow');
};
if (player.paused()) {
player.play();
player.one('playing', playFunction);
} else {
playFunction();
}
return false; // this will stop the code to not set a new player.one.
}
}
} else { // It is a text
var hasRanges = typeof an.ranges !== 'undefined' && typeof an.ranges[0] !== 'undefined';
var startOffset = hasRanges ? an.ranges[0].startOffset : '';
var endOffset = hasRanges ? an.ranges[0].endOffset : '';
if (typeof startOffset !== 'undefined' && typeof endOffset !== 'undefined') {
$(an.highlights).parent().find('.annotator-hl').removeClass('api');
// change the color
$(an.highlights).addClass('api');
// animate to the annotation
$('html, body').animate({
scrollTop: $(an.highlights[0]).offset().top
}, 'slow');
}
}
}
}
}

View File

@@ -1,1078 +0,0 @@
/*
RangeSlider v1.0 (https://github.com/danielcebrian/rangeslider-videojs)
Copyright (C) 2014 Daniel Cebrian Robles
License: https://github.com/danielcebrian/rangeslider-videojs/blob/master/License.rst
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
//----------------Load Plugin----------------//
(function (){
//-- Load RangeSlider plugin in videojs
function RangeSlider_(options){
var player = this;
player.rangeslider=new RangeSlider(player, options);
//When the DOM and the video media is loaded
function initialVideoFinished(event) {
var plugin = player.rangeslider;
//All components will be initialize after they have been loaded by videojs
for (var index in plugin.components) {
plugin.components[index].init_();
}
if (plugin.options.hidden)
plugin.hide(); //Hide the Range Slider
if(plugin.options.locked)
plugin.lock(); //Lock the Range Slider
if(plugin.options.panel==false)
plugin.hidePanel(); //Hide the second Panel
if(plugin.options.controlTime==false)
plugin.hidecontrolTime(); //Hide the control time panel
plugin._reset();
player.trigger('loadedRangeSlider'); //Let know if the Range Slider DOM is ready
}
if (player.techName == 'Youtube'){
//Detect youtube problems
player.one('error', function(e){
switch (player.error) {
case 2:
alert("The request contains an invalid parameter value. For example, this error occurs if you specify a video ID that does not have 11 characters, or if the video ID contains invalid characters, such as exclamation points or asterisks.");
case 5:
alert("The requested content cannot be played in an HTML5 player or another error related to the HTML5 player has occurred.");
case 100:
alert("The video requested was not found. This error occurs when a video has been removed (for any reason) or has been marked as private.");
break;
case 101:
alert("The owner of the requested video does not allow it to be played in embedded players.");
break;
case 150:
alert("The owner of the requested video does not allow it to be played in embedded players.");
break;
default:
alert("Unknown Error");
break;
}
});
player.on('firstplay', initialVideoFinished);
}else{
player.one('playing', initialVideoFinished);
}
console.log("Loaded Plugin RangeSlider");
}
videojs.plugin('rangeslider', RangeSlider_);
//-- Plugin
function RangeSlider(player,options){
var player = player || this;
this.player = player;
this.components = {}; // holds any custom components we add to the player
options = options || {}; // plugin options
if(!options.hasOwnProperty('locked'))
options.locked = false; // lock slider handles
if(!options.hasOwnProperty('hidden'))
options.hidden = true; // hide slider handles
if(!options.hasOwnProperty('panel'))
options.panel = true; // Show Second Panel
if(!options.hasOwnProperty('controlTime'))
options.controlTime = true; // Show Control Time to set the arrows in the edition
this.options = options;
this.init();
}
//-- Methods
RangeSlider.prototype = {
/*Constructor*/
init:function(){
var player = this.player || {};
this.updatePrecision = 3;
//position in second of the arrows
this.start = 0;
this.end = 0;
//components of the plugin
var controlBar = player.controlBar;
var seekBar = controlBar.progressControl.seekBar;
this.components.RSTimeBar = seekBar.RSTimeBar;
this.components.ControlTimePanel = controlBar.ControlTimePanel;
//Save local component
this.rstb = this.components.RSTimeBar;
this.box = this.components.SeekRSBar = this.rstb.SeekRSBar;
this.bar = this.components.SelectionBar = this.box.SelectionBar;
this.left = this.components.SelectionBarLeft = this.box.SelectionBarLeft;
this.right = this.components.SelectionBarRight = this.box.SelectionBarRight;
this.tp = this.components.TimePanel = this.box.TimePanel;
this.tpl = this.components.TimePanelLeft = this.tp.TimePanelLeft;
this.tpr = this.components.TimePanelRight = this.tp.TimePanelRight;
this.ctp = this.components.ControlTimePanel;
this.ctpl = this.components.ControlTimePanelLeft = this.ctp.ControlTimePanelLeft;
this.ctpr = this.components.ControlTimePanelRight = this.ctp.ControlTimePanelRight;
},
lock: function() {
this.options.locked = true;
this.ctp.enable(false);
if (typeof this.box != 'undefined')
videojs.addClass(this.box.el_, 'locked');
},
unlock: function() {
this.options.locked = false;
this.ctp.enable();
if (typeof this.box !='undefined')
videojs.removeClass(this.box.el_, 'locked');
},
show:function(){
this.options.hidden = false;
if (typeof this.rstb !='undefined'){
this.rstb.show();
if (this.options.controlTime)
this.showcontrolTime();
}
},
hide:function(){
this.options.hidden = true;
if (typeof this.rstb !='undefined'){
this.rstb.hide();
this.ctp.hide();
}
},
showPanel:function(){
this.options.panel = true;
if (typeof this.tp !='undefined')
videojs.removeClass(this.tp.el_, 'disable');
},
hidePanel:function(){
this.options.panel = false;
if (typeof this.tp !='undefined')
videojs.addClass(this.tp.el_, 'disable');
},
showcontrolTime:function(){
this.options.controlTime = true;
if (typeof this.ctp !='undefined')
this.ctp.show();
},
hidecontrolTime:function(){
this.options.controlTime = false;
if (typeof this.ctp !='undefined')
this.ctp.hide();
},
setValue: function(index, seconds, writeControlTime) {
//index = 0 for the left Arrow and 1 for the right Arrow. Value in seconds
var writeControlTime = typeof writeControlTime!='undefined'?writeControlTime:true;
var percent = this._percent(seconds);
var isValidIndex = (index === 0 || index === 1);
var isChangeable = !this.locked;
if(isChangeable && isValidIndex)
this.box.setPosition(index,percent,writeControlTime);
},
setValues: function(start, end, writeControlTime) {
//index = 0 for the left Arrow and 1 for the right Arrow. Value in seconds
var writeControlTime = typeof writeControlTime!='undefined'?writeControlTime:true;
this._reset();
this._setValuesLocked(start,end,writeControlTime);
},
getValues: function() { //get values in seconds
var values = {}, start, end;
start = this.start || this._getArrowValue(0);
end = this.end || this._getArrowValue(1);
return {start:start, end:end};
},
playBetween: function(start, end,showRS) {
showRS = typeof showRS == 'undefined'?true:showRS;
this.player.currentTime(start);
this.player.play();
if (showRS){
this.show();
this._reset();
}else{
this.hide();
}
this._setValuesLocked(start,end);
this.bar.activatePlay(start,end);
},
loop: function (start, end, show) {
var player = this.player;
if (player) {
player.on("pause", videojs.bind(this, function () {
this.looping = false;
}));
show = typeof show === 'undefined' ? true : show;
if (show) {
this.show();
this._reset();
}
else {
this.hide();
}
this._setValuesLocked(start, end);
this.timeStart = start;
this.timeEnd = end;
this.looping = true;
this.player.currentTime(start);
this.player.play();
this.player.on("timeupdate", videojs.bind(this, this.bar.process_loop));
}
},
_getArrowValue: function(index) {
var index = index || 0;
var duration = this.player.duration();
duration = typeof duration == 'undefined'? 0 : duration;
var percentage = this[index === 0? "left" : "right"].el_.style.left.replace("%","");
if (percentage == "")
percentage = index === 0? 0 : 100;
return videojs.round(this._seconds(percentage / 100),this.updatePrecision-1);
},
_percent: function(seconds) {
var duration = this.player.duration();
if(isNaN(duration)) {
return 0;
}
return Math.min(1, Math.max(0, seconds / duration));
},
_seconds: function(percent) {
var duration = this.player.duration();
if(isNaN(duration)) {
return 0;
}
return Math.min(duration, Math.max(0, percent * duration));
},
_reset: function() {
var duration = this.player.duration();
this.tpl.el_.style.left = '0%';
this.tpr.el_.style.left = '100%';
this._setValuesLocked(0,duration);
},
_setValuesLocked: function(start,end, writeControlTime){
var triggerSliderChange = typeof writeControlTime!='undefined';
var writeControlTime = typeof writeControlTime!='undefined'?writeControlTime:true;
if(this.options.locked) {
this.unlock();//It is unlocked to change the bar position. In the end it will return the value.
this.setValue(0,start,writeControlTime);
this.setValue(1,end,writeControlTime);
this.lock();
}else{
this.setValue(0,start,writeControlTime);
this.setValue(1,end,writeControlTime);
}
// Trigger slider change
if (triggerSliderChange) {
this._triggerSliderChange();
}
},
_checkControlTime: function(index,TextInput,timeOld){
var h = TextInput[0],
m = TextInput[1],
s = TextInput[2],
newHour = h.value,
newMin = m.value,
newSec = s.value,
obj, objNew, objOld;
index = index || 0;
if (newHour != timeOld[0]){
obj = h;
objNew = newHour;
objOld = timeOld[0];
}else if (newMin != timeOld[1]){
obj = m;
objNew = newMin;
objOld = timeOld[1];
}else if(newSec != timeOld[2]){
obj = s;
objNew = newSec;
objOld = timeOld[2];
}else{
return false;
}
var duration = this.player.duration() || 0,
durationSel;
var intRegex = /^\d+$/;//check if the objNew is an integer
if(!intRegex.test(objNew) || objNew>60){
objNew = objNew ==""?"":objOld;
}
newHour = newHour == ""?0:newHour;
newMin = newMin == ""?0:newMin;
newSec = newSec == ""?0:newSec;
durationSel = videojs.TextTrack.prototype.parseCueTime(newHour+":"+newMin+":"+newSec);
if (durationSel > duration){
obj.value = objOld;
obj.style.border = "1px solid red";
}else{
obj.value = objNew;
h.style.border = m.style.border = s.style.border = "1px solid transparent";
this.setValue(index,durationSel,false);
// Trigger slider change
this._triggerSliderChange();
}
if (index===1){
var oldTimeLeft = this.ctpl.el_.children,
durationSelLeft = videojs.TextTrack.prototype.parseCueTime(oldTimeLeft[0].value+":"+oldTimeLeft[1].value+":"+oldTimeLeft[2].value);
if (durationSel < durationSelLeft){
obj.style.border = "1px solid red";
}
}else{
var oldTimeRight = this.ctpr.el_.children,
durationSelRight = videojs.TextTrack.prototype.parseCueTime(oldTimeRight[0].value+":"+oldTimeRight[1].value+":"+oldTimeRight[2].value);
if (durationSel > durationSelRight){
obj.style.border = "1px solid red";
}
}
},
_triggerSliderChange: function(){
this.player.trigger("sliderchange");
}
};
//----------------Public Functions----------------//
//-- Public Functions added to video-js
//Lock the Slider bar and it will not be possible to change the arrow positions
videojs.Player.prototype.lockSlider = function(){
return this.rangeslider.lock();
};
//Unlock the Slider bar and it will be possible to change the arrow positions
videojs.Player.prototype.unlockSlider = function(){
return this.rangeslider.unlock();
};
//Show the Slider Bar Component
videojs.Player.prototype.showSlider = function(){
return this.rangeslider.show();
};
//Hide the Slider Bar Component
videojs.Player.prototype.hideSlider = function(){
return this.rangeslider.hide();
};
//Show the Panel with the seconds of the selection
videojs.Player.prototype.showSliderPanel = function(){
return this.rangeslider.showPanel();
};
//Hide the Panel with the seconds of the selection
videojs.Player.prototype.hideSliderPanel = function(){
return this.rangeslider.hidePanel();
};
//Show the control Time to edit the position of the arrows
videojs.Player.prototype.showControlTime = function(){
return this.rangeslider.showcontrolTime();
};
//Hide the control Time to edit the position of the arrows
videojs.Player.prototype.hideControlTime = function(){
return this.rangeslider.hidecontrolTime();
};
//Set a Value in second for both arrows
videojs.Player.prototype.setValueSlider = function(start, end){
return this.rangeslider.setValues(start, end);
};
//The video will be played in a selected section
videojs.Player.prototype.playBetween = function(start, end){
return this.rangeslider.playBetween(start, end);
};
//The video will loop between to values
videojs.Player.prototype.loopBetween = function (start, end) {
return this.rangeslider.loop(start, end);
};
//Set a Value in second for the arrows
videojs.Player.prototype.getValueSlider = function(){
return this.rangeslider.getValues();
};
//----------------Create new Components----------------//
//--Charge the new Component into videojs
videojs.SeekBar.prototype.options_.children.RSTimeBar={}; //Range Slider Time Bar
videojs.ControlBar.prototype.options_.children.ControlTimePanel={}; //Panel with the time of the range slider
//-- Design the new components
/**
* Range Slider Time Bar
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.RSTimeBar = videojs.Component.extend({
/** @constructor */
init: function(player, options){
videojs.Component.call(this, player, options);
}
});
videojs.RSTimeBar.prototype.init_ = function(){
this.rs = this.player_.rangeslider;
};
videojs.RSTimeBar.prototype.options_ = {
children: {
'SeekRSBar': {}
}
};
videojs.RSTimeBar.prototype.createEl = function(){
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-timebar-RS',
innerHTML: ''
});
};
/**
* Seek Range Slider Bar and holder for the selection bars
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.SeekRSBar = videojs.Component.extend({
/** @constructor */
init: function(player, options){
videojs.Component.call(this, player, options);
this.on('mousedown', this.onMouseDown);
}
});
videojs.SeekRSBar.prototype.init_ =function(){
this.rs = this.player_.rangeslider;
};
videojs.SeekRSBar.prototype.options_ = {
children: {
'SelectionBar': {},
'SelectionBarLeft': {},
'SelectionBarRight': {},
'TimePanel': {},
}
};
videojs.SeekRSBar.prototype.createEl = function(){
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-rangeslider-holder'
});
};
videojs.SeekRSBar.prototype.onMouseDown = function(event) {
event.preventDefault();
videojs.blockTextSelection();
if(!this.rs.options.locked) {
videojs.on(document, "mousemove", videojs.bind(this,this.onMouseMove));
videojs.on(document, "mouseup", videojs.bind(this,this.onMouseUp));
}
};
videojs.SeekRSBar.prototype.onMouseUp = function(event) {
videojs.off(document, "mousemove", this.onMouseMove, false);
videojs.off(document, "mouseup", this.onMouseUp, false);
};
videojs.SeekRSBar.prototype.onMouseMove = function(event) {
var left = this.calculateDistance(event);
if (this.rs.left.pressed)
this.setPosition(0,left);
else if (this.rs.right.pressed)
this.setPosition(1,left);
//Fix a problem with the presition in the display time
var currentTimeDisplay = this.player_.controlBar.currentTimeDisplay.content;
currentTimeDisplay.innerHTML = '<span class="vjs-control-text">Current Time </span>'+vjs.formatTime(this.rs._seconds(left), this.player_.duration());
// Trigger slider change
if (this.rs.left.pressed||this.rs.right.pressed) {
this.rs._triggerSliderChange();
}
};
videojs.SeekRSBar.prototype.setPosition = function(index,left,writeControlTime) {
var writeControlTime = typeof writeControlTime!='undefined'?writeControlTime:true;
//index = 0 for left side, index = 1 for right side
var index = index || 0;
// Position shouldn't change when handle is locked
if(this.rs.options.locked)
return false;
// Check for invalid position
if(isNaN(left))
return false;
// Check index between 0 and 1
if(!(index === 0 || index === 1))
return false;
// Alias
var ObjLeft = this.rs.left.el_,
ObjRight = this.rs.right.el_,
Obj = this.rs[index === 0 ? 'left' : 'right'].el_,
tpr = this.rs.tpr.el_,
tpl = this.rs.tpl.el_,
bar = this.rs.bar,
ctp = this.rs[index === 0 ? 'ctpl' : 'ctpr'].el_;
//Check if left arrow is passing the right arrow
if ((index === 0 ?bar.updateLeft(left):bar.updateRight(left))){
Obj.style.left = (left * 100) + '%';
index === 0 ?bar.updateLeft(left):bar.updateRight(left);
this.rs[index === 0 ? 'start' : 'end'] = this.rs._seconds(left);
//Fix the problem when you press the button and the two arrow are underhand
//left.zIndex = 10 and right.zIndex=20. This is always less in this case:
if (index === 0){
if((left) >= 0.9)
ObjLeft.style.zIndex = 25;
else
ObjLeft.style.zIndex = 10;
}
//-- Panel
var TimeText = videojs.formatTime(this.rs._seconds(left)),
tplTextLegth = tpl.children[0].innerHTML.length;
var MaxP,MinP,MaxDisP;
if (tplTextLegth<=4) //0:00
MaxDisP = this.player_.isFullScreen?3.25:6.5;
else if(tplTextLegth<=5)//00:00
MaxDisP = this.player_.isFullScreen?4:8;
else//0:00:00
MaxDisP = this.player_.isFullScreen?5:10;
if(TimeText.length<=4){ //0:00
MaxP = this.player_.isFullScreen?97:93;
MinP = this.player_.isFullScreen?0.1:0.5;
}else if(TimeText.length<=5){//00:00
MaxP = this.player_.isFullScreen?96:92;
MinP = this.player_.isFullScreen?0.1:0.5;
}else{//0:00:00
MaxP = this.player_.isFullScreen?95:91;
MinP = this.player_.isFullScreen?0.1:0.5;
}
if (index===0){
tpl.style.left = Math.max(MinP,Math.min(MaxP,(left * 100 - MaxDisP/2))) + '%';
if ((tpr.style.left.replace("%","") - tpl.style.left.replace("%",""))<=MaxDisP)
tpl.style.left = Math.max(MinP,Math.min(MaxP,tpr.style.left.replace("%","")-MaxDisP)) + '%';
tpl.children[0].innerHTML = TimeText;
}else{
tpr.style.left = Math.max(MinP,Math.min(MaxP,(left * 100 - MaxDisP/2))) + '%';
if (((tpr.style.left.replace("%","")||100) - tpl.style.left.replace("%",""))<=MaxDisP)
tpr.style.left = Math.max(MinP,Math.min(MaxP,tpl.style.left.replace("%","")-0+MaxDisP)) + '%';
tpr.children[0].innerHTML = TimeText;
}
//-- Control Time
if(writeControlTime){
var time = TimeText.split(":"),
h,m,s;
if(time.length == 2){
h = 00;
m = time[0];
s = time[1];
}else{
h = time[0];
m = time[1];
s = time[2];
}
ctp.children[0].value = h;
ctp.children[1].value = m;
ctp.children[2].value = s;
}
}
return true;
};
videojs.SeekRSBar.prototype.calculateDistance = function(event){
var rstbX = this.getRSTBX();
var rstbW = this.getRSTBWidth();
var handleW = this.getWidth();
// Adjusted X and Width, so handle doesn't go outside the bar
rstbX = rstbX + (handleW / 2);
rstbW = rstbW - handleW;
// Percent that the click is through the adjusted area
return Math.max(0, Math.min(1, (event.pageX - rstbX) / rstbW));
};
videojs.SeekRSBar.prototype.getRSTBWidth = function() {
return this.el_.offsetWidth;
};
videojs.SeekRSBar.prototype.getRSTBX = function() {
return videojs.findPosition(this.el_).left;
};
videojs.SeekRSBar.prototype.getWidth = function() {
return this.rs.left.el_.offsetWidth;//does not matter left or right
};
/**
* This is the bar with the selection of the RangeSlider
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.SelectionBar = videojs.Component.extend({
/** @constructor */
init: function(player, options){
videojs.Component.call(this, player, options);
this.on('mouseup', this.onMouseUp);
this.fired = false;
}
});
videojs.SelectionBar.prototype.init_ = function(){
this.rs = this.player_.rangeslider;
};
videojs.SelectionBar.prototype.createEl = function(){
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-selectionbar-RS'
});
};
videojs.SelectionBar.prototype.onMouseUp = function(){
var start = this.rs.left.el_.style.left.replace("%",""),
end = this.rs.right.el_.style.left.replace("%",""),
duration = this.player_.duration(),
precision = this.rs.updatePrecision,
segStart = videojs.round(start * duration/100, precision),
segEnd = videojs.round(end * duration/100, precision);
this.player_.currentTime(segStart);
this.player_.play();
this.rs.bar.activatePlay(segStart,segEnd);
};
videojs.SelectionBar.prototype.updateLeft = function(left) {
var rightVal = this.rs.right.el_.style.left!=''?this.rs.right.el_.style.left:100;
var right = parseFloat(rightVal) / 100;
var width = videojs.round((right - left),this.rs.updatePrecision); //round necessary for not get 0.6e-7 for example that it's not able for the html css width
//(right+0.00001) is to fix the precision of the css in html
if(left <= (right+0.00001)) {
this.rs.bar.el_.style.left = (left * 100) + '%';
this.rs.bar.el_.style.width = (width * 100) + '%';
return true;
}
return false;
};
videojs.SelectionBar.prototype.updateRight = function(right) {
var leftVal = this.rs.left.el_.style.left!=''?this.rs.left.el_.style.left:0;
var left = parseFloat(leftVal) / 100;
var width = videojs.round((right - left),this.rs.updatePrecision);//round necessary for not get 0.6e-7 for example that it's not able for the html css width
//(right+0.00001) is to fix the precision of the css in html
if((right+0.00001) >= left) {
this.rs.bar.el_.style.width = (width * 100) + '%';
this.rs.bar.el_.style.left = ((right - width) * 100) + '%';
return true;
}
return false;
};
videojs.SelectionBar.prototype.activatePlay = function(start,end){
this.timeStart = start;
this.timeEnd = end;
this.suspendPlay();
this.player_.on("timeupdate", videojs.bind(this,this._processPlay));
};
videojs.SelectionBar.prototype.suspendPlay = function(){
this.fired = false;
this.player_.off("timeupdate", videojs.bind(this,this._processPlay));
};
videojs.SelectionBar.prototype._processPlay = function (){
//Check if current time is between start and end
if(this.player_.currentTime() >= this.timeStart && (this.timeEnd < 0 || this.player_.currentTime() < this.timeEnd)){
if(this.fired){ //Do nothing if start has already been called
return;
}
this.fired = true; //Set fired flag to true
}else{
if(!this.fired){ //Do nothing if end has already been called
return;
}
this.fired = false; //Set fired flat to false
this.player_.pause(); //Call end function
this.player_.currentTime(this.timeEnd);
this.suspendPlay();
}
};
videojs.SelectionBar.prototype.process_loop = function () {
var player = this.player;
if (player && this.looping) {
var current_time = player.currentTime();
if (current_time < this.timeStart || this.timeEnd > 0 && this.timeEnd < current_time) {
player.currentTime(this.timeStart);
}
}
};
/**
* This is the left arrow to select the RangeSlider
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.SelectionBarLeft = videojs.Component.extend({
/** @constructor */
init: function(player, options){
videojs.Component.call(this, player, options);
this.on('mousedown', this.onMouseDown);
this.pressed = false;
}
});
videojs.SelectionBarLeft.prototype.init_ = function(){
this.rs = this.player_.rangeslider;
};
videojs.SelectionBarLeft.prototype.createEl = function(){
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-rangeslider-handle vjs-selectionbar-left-RS',
innerHTML: '<div class="vjs-selectionbar-arrow-RS"></div><div class="vjs-selectionbar-line-RS"></div>'
});
};
videojs.SelectionBarLeft.prototype.onMouseDown = function(event) {
event.preventDefault();
videojs.blockTextSelection();
if(!this.rs.options.locked) {
this.pressed = true;
videojs.on(document, "mouseup", videojs.bind(this,this.onMouseUp));
videojs.addClass(this.el_, 'active');
}
};
videojs.SelectionBarLeft.prototype.onMouseUp = function(event) {
videojs.off(document, "mouseup", this.onMouseUp, false);
videojs.removeClass(this.el_, 'active');
if(!this.rs.options.locked) {
this.pressed = false;
}
};
/**
* This is the right arrow to select the RangeSlider
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.SelectionBarRight = videojs.Component.extend({
/** @constructor */
init: function(player, options){
videojs.Component.call(this, player, options);
this.on('mousedown', this.onMouseDown);
this.pressed = false;
}
});
videojs.SelectionBarRight.prototype.init_ = function(){
this.rs = this.player_.rangeslider;
};
videojs.SelectionBarRight.prototype.createEl = function(){
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-rangeslider-handle vjs-selectionbar-right-RS',
innerHTML: '<div class="vjs-selectionbar-arrow-RS"></div><div class="vjs-selectionbar-line-RS"></div>'
});
};
videojs.SelectionBarRight.prototype.onMouseDown = function(event) {
event.preventDefault();
videojs.blockTextSelection();
if(!this.rs.options.locked) {
this.pressed = true;
videojs.on(document, "mouseup", videojs.bind(this,this.onMouseUp));
videojs.addClass(this.el_, 'active');
}
};
videojs.SelectionBarRight.prototype.onMouseUp = function(event) {
videojs.off(document, "mouseup", this.onMouseUp, false);
videojs.removeClass(this.el_, 'active');
if(!this.rs.options.locked) {
this.pressed = false;
}
};
/**
* This is the time panel
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.TimePanel = videojs.Component.extend({
/** @constructor */
init: function(player, options){
videojs.Component.call(this, player, options);
}
});
videojs.TimePanel.prototype.init_ = function(){
this.rs = this.player_.rangeslider;
};
videojs.TimePanel.prototype.options_ = {
children: {
'TimePanelLeft': {},
'TimePanelRight': {},
}
};
videojs.TimePanel.prototype.createEl = function(){
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-timepanel-RS'
});
};
/**
* This is the left time panel
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.TimePanelLeft = videojs.Component.extend({
/** @constructor */
init: function(player, options){
videojs.Component.call(this, player, options);
}
});
videojs.TimePanelLeft.prototype.init_ = function(){
this.rs = this.player_.rangeslider;
};
videojs.TimePanelLeft.prototype.createEl = function(){
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-timepanel-left-RS',
innerHTML: '<span class="vjs-time-text">00:00</span>'
});
};
/**
* This is the right time panel
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.TimePanelRight = videojs.Component.extend({
/** @constructor */
init: function(player, options){
videojs.Component.call(this, player, options);
}
});
videojs.TimePanelRight.prototype.init_ = function(){
this.rs = this.player_.rangeslider;
};
videojs.TimePanelRight.prototype.createEl = function(){
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-timepanel-right-RS',
innerHTML: '<span class="vjs-time-text">00:00</span>'
});
};
/**
* This is the control time panel
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.ControlTimePanel= videojs.Component.extend({
/** @constructor */
init: function(player, options){
videojs.Component.call(this, player, options);
}
});
videojs.ControlTimePanel.prototype.init_ = function(){
this.rs = this.player_.rangeslider;
};
videojs.ControlTimePanel.prototype.options_ = {
children: {
'ControlTimePanelLeft': {},
'ControlTimePanelRight': {},
}
};
videojs.ControlTimePanel.prototype.createEl = function(){
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-controltimepanel-RS vjs-control',
});
};
videojs.ControlTimePanel.prototype.enable = function(enable){
var enable = typeof enable != 'undefined'? enable:true;
this.rs.ctpl.el_.children[0].disabled = enable?"":"disabled";
this.rs.ctpl.el_.children[1].disabled = enable?"":"disabled";
this.rs.ctpl.el_.children[2].disabled = enable?"":"disabled";
this.rs.ctpr.el_.children[0].disabled = enable?"":"disabled";
this.rs.ctpr.el_.children[1].disabled = enable?"":"disabled";
this.rs.ctpr.el_.children[2].disabled = enable?"":"disabled";
};
/**
* This is the control left time panel
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.ControlTimePanelLeft = videojs.Component.extend({
/** @constructor */
init: function(player, options){
videojs.Component.call(this, player, options);
this.on('keyup', this.onKeyUp);
this.on('keydown', this.onKeyDown);
}
});
videojs.ControlTimePanelLeft.prototype.init_ = function(){
this.rs = this.player_.rangeslider;
this.timeOld = {};
};
videojs.ControlTimePanelLeft.prototype.createEl = function(){
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-controltimepanel-left-RS',
innerHTML: 'Start: <input type="text" id="controltimepanel" maxlength="2" value="00"/>:<input type="text" id="controltimepanel" maxlength="2" value="00"/>:<input type="text" id="controltimepanel" maxlength="2" value="00"/>'
});
};
videojs.ControlTimePanelLeft.prototype.onKeyDown = function(event) {
this.timeOld[0] = this.el_.children[0].value;
this.timeOld[1] = this.el_.children[1].value;
this.timeOld[2] = this.el_.children[2].value;
};
videojs.ControlTimePanelLeft.prototype.onKeyUp = function(event) {
this.rs._checkControlTime(0,this.el_.children,this.timeOld);
};
/**
* This is the control right time panel
* @param {videojs.Player|Object} player
* @param {Object=} options
* @constructor
*/
videojs.ControlTimePanelRight = videojs.Component.extend({
/** @constructor */
init: function(player, options){
videojs.Component.call(this, player, options);
this.on('keyup', this.onKeyUp);
this.on('keydown', this.onKeyDown);
}
});
videojs.ControlTimePanelRight.prototype.init_ = function(){
this.rs = this.player_.rangeslider;
this.timeOld = {};
};
videojs.ControlTimePanelRight.prototype.createEl = function(){
return videojs.Component.prototype.createEl.call(this, 'div', {
className: 'vjs-controltimepanel-right-RS',
innerHTML: 'End: <input type="text" id="controltimepanel" maxlength="2" value="00"/>:<input type="text" id="controltimepanel" maxlength="2" value="00"/>:<input type="text" id="controltimepanel" maxlength="2" value="00"/>'
});
};
videojs.ControlTimePanelRight.prototype.onKeyDown = function(event) {
this.timeOld[0] = this.el_.children[0].value;
this.timeOld[1] = this.el_.children[1].value;
this.timeOld[2] = this.el_.children[2].value;
};
videojs.ControlTimePanelRight.prototype.onKeyUp = function(event) {
this.rs._checkControlTime(1,this.el_.children,this.timeOld);
};
})();

View File

@@ -1,110 +0,0 @@
/*
Reply Annotator Plugin v1.0 (https://github.com/danielcebrian/reply-annotator)
Copyright (C) 2014 Daniel Cebrian Robles
License: https://github.com/danielcebrian/reply-annotator/blob/master/License.rst
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// Generated by CoffeeScript 1.6.3
var _ref,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
Annotator.Plugin.Reply = (function(_super) {
__extends(Reply, _super);
function Reply() {
this.pluginSubmit = __bind(this.pluginSubmit, this);
this.updateField = __bind(this.updateField, this);
_ref = Reply.__super__.constructor.apply(this, arguments);
return _ref;
}
Reply.prototype.field = null;
Reply.prototype.input = null;
Reply.prototype.pluginInit = function() {
console.log("Reply-pluginInit");
//Check that annotator is working
if (!Annotator.supported()) {
return;
}
//-- Editor
this.field = this.annotator.editor.addField({
type: 'input', //options (textarea,input,select,checkbox)
load: this.updateField,
submit: this.pluginSubmit,
});
var newfield = Annotator.$('<li class="annotator-item reply-item" style="display:none"><span class="parent-annotation">0</span></li>');//reply-item is the parent value
Annotator.$(this.field).replaceWith(newfield);
this.field=newfield[0];
//-- Viewer
var newview = this.annotator.viewer.addField({
load: this.updateViewer,
});
return this.input = $(this.field).find(':input');
};
// New JSON for the database
Reply.prototype.pluginSubmit = function(field, annotation) {
// since each annotation has their own reply item, this "find" is element specific
var replyItem = $(this.annotator.editor.element).find(".reply-item span.parent-annotation");
// checks to see if the current annotation is a reply by checking parent numbers
var parent = replyItem.html() !== '' ? replyItem.html() : '0';
// if the parent number is not empty or zero, we know that this is a comment
if (parent !== '0') {
annotation.media = 'comment';
}
// apparently some browsers continue adding <font> tags here for nonreplies
// this will check and set to 0 (nonreply) if it fails
if (parseInt(parent, 10) === NaN){
parent = '0';
}
// set 0, because it is not a reply
annotation.parent = parent;
return annotation.parent;
};
Reply.prototype.updateViewer = function(field, annotation) {
var self = this,
field = $(field),
ret = field.addClass('reply-viewer-annotator').html(function() {
var string;
return self;
});
field.remove();
this.annotation = annotation;
//Create the actions for the buttons
return ret;
};
Reply.prototype.updateField = function(field, annotation) {
//reset parent value
var replyItem = $(this.annotator.editor.element).find(".reply-item span.parent-annotation");
return replyItem.html('0');
};
return Reply;
})(Annotator.Plugin);

View File

@@ -1,186 +0,0 @@
/*
Rich Text Annotator Plugin v1.0 (https://github.com/danielcebrian/richText-annotator)
Copyright (C) 2014 Daniel Cebrian Robles
License: https://github.com/danielcebrian/richText-annotator/blob/master/License.rst
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
var _ref,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
Annotator.Plugin.RichText = (function(_super) {
__extends(RichText, _super);
//Default tinymce configuration
RichText.prototype.options = {
tinymce:{
selector: "li.annotator-item textarea",
skin: 'studio-tmce4',
formats: {
code: {
inline: 'code'
}
},
codemirror: {
path: "/static/js/vendor"
},
plugins: "image link codemirror media",
menubar: false,
toolbar_items_size: 'small',
extended_valid_elements : "iframe[src|frameborder|style|scrolling|class|width|height|name|align|id]",
toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image media | code ",
resize: "both",
}
};
function RichText(element,options) {
_ref = RichText.__super__.constructor.apply(this, arguments);
return _ref;
};
RichText.prototype.pluginInit = function() {
console.log("RichText-pluginInit");
var annotator = this.annotator,
editor = this.annotator.editor;
// check that annotator is working
if (!Annotator.supported()) {
return;
}
// editor Setup
annotator.editor.addField({
type: 'input',
submit: this.submitEditor,
load: this.updateEditor,
});
// viewer setup
annotator.viewer.addField({
load: this.updateViewer,
});
// makes sure that tinymce is hidden and shown along with the editor
annotator.subscribe("annotationEditorShown", function() {
$(annotator.editor.element).find('.mce-tinymce')[0].style.display = 'block';
annotator.editor.checkOrientation();
});
annotator.subscribe("annotationEditorHidden", function() {
$(annotator.editor.element).find('.mce-tinymce')[0].style.display = 'none';
});
// set listener for tinymce;
this.options.tinymce.setup = function(ed) {
// note that the following does not work in Firefox, fix using submitEditor function
ed.on('change', function(e) {
// set the modification in the textarea of annotator
$(editor.element).find('textarea')[0].value = tinymce.activeEditor.getContent();
});
// creates a function called whenever editor is resized
ed.on('init', function(mceInstance) {
// get win means this event activates when window is resized
tinymce.dom.Event.bind(ed.getWin(), 'resize', function(e){
// mceInstance.target gets the editor, its id is used to retrieved iframe
$("#"+mceInstance.target.id+"_ifr").css('min-width', '400px');
});
});
// new button to add Rubrics of the url https://gteavirtual.org/rubric
ed.addButton('rubric', {
icon: 'rubric',
title : 'Insert a rubric',
onclick: function() {
ed.windowManager.open({
title: 'Insert a public rubric of the website https://gteavirtual.org/rubric',
body: [
{type: 'textbox', name: 'url', label: 'Url'}
],
onsubmit: function(e) {
// Insert content when the window form is submitted
var url = e.data.url;
var name = 'irb';
var irb;
// get the variable 'name' from the given url
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
var results = regex.exec(url);
// the rubric id
irb = results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
if (irb==''){
ed.windowManager.alert('Error: The given webpage didn\'t have a irb variable in the url');
}else{
var iframeRubric = "<iframe src='https://gteavirtual.org/rubric/?mod=portal&scr=viewrb&evt=frame&irb=" + irb + "' style='width:800px;height:600px;overflow-y: scroll;background:transparent' frameborder='0' ></iframe>";
ed.setContent(ed.getContent()+iframeRubric);
$(editor.element).find('textarea')[0].value = ed.getContent();
}
}
});
ed.insertContent('Main button');
ed.label = 'My Button';
}
});
};
// makes sure that if tinymce exists already that this removes/destroys previous version
if (tinymce.editors.length > 0) {
tinymce.remove("li.annotator-item textarea");
}
tinymce.init(this.options.tinymce);
};
/**
* Copies the content of annotation text and inserts it into the tinymce instance
*/
RichText.prototype.updateEditor = function(field, annotation) {
var text = typeof annotation.text != 'undefined' ? annotation.text : '';
tinymce.activeEditor.setContent(text);
$(field).remove(); // this is the auto create field by annotator and it is not necessary
}
/**
* Takes the text from the annotation text and makes sure it replaces the old text field
* with the richtext from tinymce.
*/
RichText.prototype.updateViewer = function(field, annotation) {
var textDiv = $(field.parentNode).find('div:first-of-type')[0];
textDiv.innerHTML = annotation.text;
$(textDiv).addClass('richText-annotation');
$(field).remove(); // this is the auto create field by annotator and it is not necessary
}
/**
* Gets called before submission. It checks to make sure tinymce content is saved
*/
RichText.prototype.submitEditor = function(field, annotation) {
var tinymceText = tinymce.activeEditor.getContent();
// Firefox has an issue where the text is not saved ("on" function doesn't work).
// this helps save it anyway.
if (annotation.text !== tinymceText) {
annotation.text = tinymce.activeEditor.getContent();
}
}
return RichText;
})(Annotator.Plugin);

View File

@@ -1,684 +0,0 @@
/*
Share Annotation Plugin v1.1 (https://github.com/danielcebrian/share-annotator)
Copyright (C) 2014 Daniel Cebrian Robles
License: https://github.com/danielcebrian/share-annotator/blob/master/License.rst
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
var _ref,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
Annotator.Plugin.Share = (function(_super) {
__extends(Share, _super);
// Default Share configuration
Share.prototype.options = {
shareIn: ['facebook', 'twitter', 'email', 'google'],
getUrl: {
'facebook': function(title, link, noteText) {
return 'https://www.facebook.com/sharer/sharer.php?s=100&p[url]=' + link + '&p[title]=' + encodeURIComponent('Open Video Annotation') + '&p[summary]=' + noteText;
},
'twitter': function(title, link, noteText) {
return 'https://twitter.com/intent/tweet?original_referer=' + link + '&source=tweetbutton&url=' + link + "&via=OpenVideoAnnotation&text=" + encodeURIComponent('I want to share the following Open Video Annotation: ');
},
'google': function(title, link, noteText) {
return 'https://plus.google.com/share?url=' + link;
},
'email': function(title, link, noteText){
return 'mailto:?subject=' + title + '&body=' + link;
}
},
baseUrl: '', // baseUrl = the base url for all the shared annotations
};
function Share(element, options) {
if (typeof options !== 'undefined') {
this.options.shareIn = typeof options.shareIn !== 'undefined' ? options.shareIn : this.options.shareIn;
}
this.buildHTMLShareButton = __bind(this.buildHTMLShareButton, this);
this.runningAPI = __bind(this.runningAPI, this);
this.updateViewer = __bind(this.updateViewer, this);
_ref = Share.__super__.constructor.apply(this, arguments);
return _ref;
}
Share.prototype.field = null;
Share.prototype.input = null;
Share.prototype.pluginInit = function() {
// Check that annotator is working
if (!Annotator.supported()) {
return;
}
// -- Editor
this.field = this.annotator.editor.addField({
type: 'input', // options (textarea, input, select, checkbox)
});
// Modify the element created with annotator to be an invisible span
var newfield = Annotator.$('<li class="annotator-item">' + this.buildHTMLShareButton('Share without saving:') + '</li>');
Annotator.$(this.field).replaceWith(newfield);
this.field=newfield[0];
// Create the actions for the buttons
this.buttonsActions(this.field, 2, this.options.baseUrl); // 2 is the method of the API that will be for share without saving
// Init the API plugin
var APIoptions = this.initAPI();
this.runAPI(APIoptions);
// -- Viewer
var newview = this.annotator.viewer.addField({
load: this.updateViewer,
});
return this.input = $(this.field).find(':input');
};
// Share button HTML
Share.prototype.buildHTMLShareButton = function(title, id) {
var title = title || '';
var id = typeof id !== 'undefined' ? 'annotationId="' + id + '"' : '';
var titleText = title !== '' ? '<div class="share-text-annotator">' + title + '</div>' : '';
var shareButton = '<div class="share-button-annotator share-button" ' + id + '></div>';
var popup = '<div class="share-popup-overlay-bg" style="z-index:30000000000"><div class="share-popup"><div class="share-popup-items"></div><div class="close-btn">Close</div></div></div>';
// checks to make sure that no popup overlay already exists (though hidden) and creates a new one if it does not exist
if ($('.share-popup-overlay-bg').length === 0) {
$('.annotator-wrapper').append(popup);
}
return '<div class="share-container-annotator">' + titleText + shareButton + '</div>';
}
// template for the design of the Share Plugin
Share.prototype.buildHTMLPopup = function(title) {
var buttons = '';
if (typeof this.options.shareIn !== 'undefined'){
this.options.shareIn.forEach(function(item) {
buttons += '<div class="share-' + item + '-annotator share-button">' + item.charAt(0).toUpperCase() + item.slice(1) + '</div>';
});
}
this.uri = (typeof this.uri !== 'undefined') ? this.uri : '';
var title = '<div class="share-popup-title">' + title.replace(":", "") + '</div>';
var copy = '<div class="share-popup-copy">Copy and Share:</div>';
var uri = '<input type="text" class="share-popup-uri" onclick="javascript:this.select();" readonly="true" value="' + this.uri + '">';
var popup = title + buttons + copy + uri;
return popup;
}
// Create the actions for the buttons
Share.prototype.buttonsActions = function(field, method, url) {
var share = this;
// hide popup when user clicks on close button
$('.close-btn').click(function() {
$('.share-popup-overlay-bg').hide();
});
// hides the popup if user clicks anywhere outside the container
$('.share-popup-overlay-bg').click(function() {
$('.share-popup-overlay-bg').hide();
});
// prevents the overlay from closing if user clicks inside the popup overlay
$('.share-popup').click(function() {
return false;
});
// Share button
$(field).find('.share-button-annotator.share-button').click(function(event) {
event.preventDefault(); // disable normal link function so that it doesn't refresh the page
var _field = this;
var ovaId = $(this).attr('annotationId');
var title = method === 1 ? 'Share' : 'Share without saving';
// share.uri will be useful for buildHTMLPopup functions
share.uri = share.createAPIURL(method, ovaId, url);
// display your popup
$('.share-popup-overlay-bg').show();
// build buttons
$('.share-popup-items').html(share.buildHTMLPopup(title));
// buttons actions
if (typeof share.options.shareIn !== 'undefined') {
share.options.shareIn.forEach(function(item) {
$('.share-' + item + '-annotator.share-button').click(function() {
var url = share.createAPIURL(method, ovaId, url);
var title = "Sharing a annotation with Open Video Annotation";
var link = encodeURIComponent(url);
var noteText = share.getSource('ovaText');
var finalUrl = '';
if (method === 1) {
var viewer = share.annotator.viewer;
var textarea = $(viewer.element).find('div:first').html();
noteText = encodeURIComponent(textarea);
}
finalUrl = typeof share.options.getUrl[item] !== 'undefined' ? share.options.getUrl[item](title, link, noteText) : '';
if (typeof share.options.getUrl[item] !== 'undefined') {
window.open(finalUrl);
}
});
});
}
});
};
Share.prototype.createAPIURL = function(method, ovaId, url) {
var annotator = this.annotator;
var editor = annotator.editor;
var method = method || 1;
var url = url || window.location.href;
url += (url.indexOf('?') >= 0) ? '&' : '?';
if (method === 1) {
var ovaId = (typeof ovaId !== 'undefined') ? ovaId : '';
url += 'ovaId=' + ovaId;
} else if (method === 2) {
var ovaText = this.getSource('ovaText') || " ";
url += 'ovaText=' + ovaText;
if (typeof editor.VideoJS !== 'undefined' && editor.VideoJS !== -1) { // Video Annotation
var ovaStart = this.getSource('ovaStart') || " ";
var ovaEnd = this.getSource('ovaEnd') || " ";
var ovaContainer = this.getSource('ovaContainer') || " ";
var ovaSrc = this.getSource('ovaSrc') || " ";
url += '&ovaStart=' + ovaStart
+ '&ovaEnd=' + ovaEnd
+ '&ovaContainer=' + ovaContainer
+ '&ovaSrc=' + ovaSrc;
} else if (typeof editor.OpenSeaDragon !== 'undefined' && editor.OpenSeaDragon !== -1) { // Image Annotation
var ovaLeft = this.getSource('ovaLeft') || " ";
var ovaTop = this.getSource('ovaTop') || " ";
var ovaWidth = this.getSource('ovaWidth') || " ";
var ovaHeight = this.getSource('ovaHeight') || " ";
var ovaLeftZoom = this.getSource('ovaLeftZoom') || " ";
var ovaTopZoom = this.getSource('ovaTopZoom') || " ";
var ovaWidthZoom = this.getSource('ovaWidthZoom') || " ";
var ovaHeightZoom = this.getSource('ovaHeightZoom') || " ";
var ovaContainer = this.getSource('ovaContainer') || " ";
var ovaSrc = this.getSource('ovaSrc') || " ";
url += '&ovaLeft=' + ovaLeft
+ '&ovaTop=' + ovaTop
+ '&ovaWidth=' + ovaWidth
+ '&ovaHeight=' + ovaHeight
+ '&ovaLeftZoom=' + ovaLeftZoom
+ '&ovaTopZoom=' + ovaTopZoom
+ '&ovaWidthZoom=' + ovaWidthZoom
+ '&ovaHeightZoom=' + ovaHeightZoom
+ '&ovaContainer=' + ovaContainer
+ '&ovaSrc=' + ovaSrc;
} else { // Text Annotation
var ovaStart = this.getSource('ovaStart') || " ";
var ovaEnd = this.getSource('ovaEnd') || " ";
var ovastartOffset = this.getSource('ovastartOffset') || " ";
var ovaendOffset = this.getSource('ovaendOffset') || " ";
url += '&ovaStart=' + ovaStart
+ '&ovaEnd=' + ovaEnd
+ '&ovastartOffset=' + ovastartOffset
+ '&ovaendOffset=' + ovaendOffset;
}
}
return url;
};
Share.prototype.getSource = function(source) {
var source = source || '';
if (source === 'ovaId') { // method 1
source = this.annotation.id;
} else { // method 2
var annotator = this.annotator;
var editor = annotator.editor;
var textarea = $(editor.element).find('textarea')[0];
if (source === 'ovaText') {
source = textarea.value;
}
if (typeof editor.VideoJS !== 'undefined' && editor.VideoJS !== -1) { // Video Annotation
if (source === 'ovaContainer') {
source = editor.VideoJS;
}
else if (source === 'ovaSrc') {
source = annotator.mplayer[editor.VideoJS].tech.options_.source.src;
} else if (source === 'ovaStart') {
source = annotator.mplayer[editor.VideoJS].rangeslider.getValues().start;
} else if (source === 'ovaEnd') {
source = annotator.mplayer[editor.VideoJS].rangeslider.getValues().end;
}
} else if (typeof editor.OpenSeaDragon !== 'undefined' && editor.OpenSeaDragon !== -1) { // Image Annotation
var annotation = editor.annotation;
if (source === 'ovaLeft') {
source = annotator.osda.rectPosition ? annotator.osda.rectPosition.left : annotation.rangePosition.left;
} else if (source === 'ovaTop') {
source = annotator.osda.rectPosition ? annotator.osda.rectPosition.top : annotation.rangePosition.top;
} else if (source === 'ovaWidth') {
source = annotator.osda.rectPosition ? annotator.osda.rectPosition.width : annotation.rangePosition.width;
} else if (source ==='ovaHeight') {
source = annotator.osda.rectPosition ? annotator.osda.rectPosition.height : annotation.rangePosition.height;
} else if (source === 'ovaLeftZoom') {
source = annotator.osda.viewer.drawer.viewport.getBounds().x;
} else if (source === 'ovaTopZoom') {
source = annotator.osda.viewer.drawer.viewport.getBounds().y;
} else if (source === 'ovaWidthZoom') {
source = annotator.osda.viewer.drawer.viewport.getBounds().width;
} else if (source === 'ovaHeightZoom') {
source = annotator.osda.viewer.drawer.viewport.getBounds().height;
} else if (source === 'ovaContainer') {
source = annotator.osda.viewer.id;
} else if (source === 'ovaSrc') {
var source = annotator.osda.viewer.source;
var tilesUrl = typeof source.tilesUrl !== 'undefined' ? source.tilesUrl : '';
var functionUrl = typeof source.getTileUrl !== 'undefined' ? source.getTileUrl : '';
source = tilesUrl !== '' ? tilesUrl : ('' + functionUrl).replace(/\s+/g, ' '); // - target.src (media source)
}
} else { // Text Annotation
var annotation = editor.annotation;
// if ranges is 0 then it is a comment
if (annotation.ranges.length > 0) {
if(source === 'ovastartOffset') {
source = annotation.ranges[0].startOffset;
} else if (source === 'ovaendOffset') {
source = annotation.ranges[0].endOffset;
} else if (source === 'ovaStart') {
source = annotation.ranges[0].start;
} else if (source === 'ovaEnd') {
source = annotation.ranges[0].end;
}
}
}
}
return encodeURIComponent(source);
};
Share.prototype.initAPI = function() {
// -- Detect API in the URL -- //
/*
The first option is to give a known id of an annotation
Example http:// url.com/#id=rTcpOjIMT2aF1apDtboC-Q
*/
var API = {};
var ovaId = this.getParameterByName('ovaId'); // Method 1 (Obligatory)
var start = this.getParameterByName('ovaStart'); // Method 2 (Obligatory)
var end = this.getParameterByName('ovaEnd'); // Method 2 (Obligatory)
var container = this.getParameterByName('ovaContainer'); // Method 2 (Obligatory)
var src = this.getParameterByName('ovaSrc'); // Method 2 (Obligatory)
var text = this.getParameterByName('ovaText'); // Method 2
var user = this.getParameterByName('ovaUser'); // Method 2
var Left = this.getParameterByName('ovaLeft'); // Method 2
var Top = this.getParameterByName('ovaTop'); // Method 2
var Width = this.getParameterByName('ovaWidth'); // Method 2
var Height = this.getParameterByName('ovaHeight'); // Method 2
var leftZoom = this.getParameterByName('ovaLeftZoom'); // Method 2
var topZoom = this.getParameterByName('ovaTopZoom'); // Method 2
var widthZoom = this.getParameterByName('ovaWidthZoom'); // Method 2
var heightZoom = this.getParameterByName('ovaHeightZoom'); // Method 2
var startOffset = this.getParameterByName('ovastartOffset'); // Method 2
var endOffset = this.getParameterByName('ovaendOffset'); // Method 2
// remove the variables from the url browser
var stripped_url = top.location.href;
if (ovaId !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaId');
if (start !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaStart');
if (end !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaEnd');
if (container !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaContainer');
if (src !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaSrc');
if (text !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaText');
if (user !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaUser');
if (Left !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaLeft');
if (Top !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaTop');
if (Width !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaWidth');
if (Height !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaHeight');
if (leftZoom !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaLeftZoom');
if (topZoom !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaTopZoom');
if (widthZoom !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaWidthZoom');
if (heightZoom !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaHeightZoom');
if (startOffset !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovastartOffset');
if (endOffset !== '') stripped_url = this.removeVariableFromURL(stripped_url, 'ovaendOffset');
window.history.pushState("object or string", "Title", stripped_url);
// Method 1 API with the Id of the annotation
// Example: http://danielcebrian.com/annotations/demo.html?&ovaId=wtva_SjnQb2HtqppDihKug
if (ovaId !== '') {
$.extend(API, {method: 1, ovaId: ovaId});
}
// Method 2 API with all the parameter to load the annotation
// Example with video: http://danielcebrian.com/annotations/demo.html?ovaContainer=vid1&ovaSrc=http%3A%2F%2Fvideo-js.zencoder.com%2Foceans-clip.mp4&ovaStart=2&ovaEnd=10&ovaText=This%20is%20test&ovaUser=Test%20User
// Example with text: http://danielcebrian.com/annotations/demo.html?ovaStart=%2Fp%5B1%5D&ovaEnd=%2Fp%5B1%5D&ovastartOffset=542&ovaendOffset=572&ovaText=API
if (start !== '' && end !== '' && container !== '' && src !== '') { // video api
$.extend(API, {method: 2, start: start, end: end, container: container, src: src, text: text, user: user});
} else if (Left !== '' && Top !== '' && Width !== '' && Height !== '' && leftZoom !== '' && topZoom !== '' && widthZoom !== '' && heightZoom !== '') { // image api
$.extend(API, {method: 2, Left: Left, Top: Top, Width: Width, Height: Height, leftZoom: leftZoom, topZoom: topZoom, widthZoom: widthZoom, heightZoom: heightZoom, container: container, src: src, text: text, user: user});
} else if (start !== '' && end !== '' && startOffset !== '' && endOffset !== '') { // text api
$.extend(API, {method: 2, start: start, end: end, startOffset: startOffset, endOffset: endOffset, text: text, user: user});
}
return API;
}
Share.prototype.runningAPI = function (annotations, API) {
var wrapper = $('.annotator-wrapper').parent()[0];
var mplayer;
var osda;
var self = this;
// Set Annotator in wrapper to fix quick DOM
$.data(wrapper, 'annotator', self.annotator);// Set the object in the span
annotator = window.annotator = $.data(wrapper, 'annotator');
mplayer = (typeof annotator.mplayer !== 'undefined') ? annotator.mplayer : [];
osda = (typeof annotator.osda !== 'undefined') ? annotator.osda : [];
// Detect if the URL has an API element
if (typeof API !== 'undefined' && typeof API.method !== 'undefined' && (parseInt(API.method, 10) === 1 || parseInt(API.method, 10) === 2)) {
if (parseInt(API.method, 10) === 1) {
var allannotations = annotator.plugins['Store'].annotations;
var ovaId = parseInt(decodeURIComponent(API.ovaId), 10);
for (var item in allannotations) {
var an = allannotations[item];
var olditem;
if (typeof an.id !== 'undefined' && parseInt(an.id, 10) === ovaId) { // this is the annotation
if (self._isVideo(an)) {// It is a video
if (typeof mplayer[an.target.container] !== 'undefined') {
var player = mplayer[an.target.container];
if (player.id_ === an.target.container) {
var anFound = an;
videojs(player.id_).ready(function() {
if (player.techName !== 'Youtube') {
player.preload('auto');
}
player.autoPlayAPI = anFound;
player.play();
});
}
}
} else if (an.media === "image") { // It is a OpenSeaDragon Annotation
if ($("div#" + an.target.container).length) {
var isOpenViewer = typeof annotator.osda !== "undefined" && typeof annotator.osda.viewer !== "undefined";
function waitingOsda(){
isOpenViewer = typeof annotator.osda !== "undefined" && typeof annotator.osda.viewer !== "undefined";
if (typeof olditem === "undefined") {
olditem = item;
}
if (!isOpenViewer) {
setTimeout(waitingOsda, 200);
} else {
an = allannotations[olditem];
$(an.highlights).parent().find('.annotator-hl').removeClass('api');
// change the color
$(an.highlights).addClass('api');
// change zoom
if (typeof annotator !== 'undefined' && typeof annotator.osda !== 'undefined') {
var currentBounds = annotator.osda.viewer.drawer.viewport.getBounds();
var bounds = typeof an.bounds !== 'undefined' ? an.bounds : {};
if (typeof bounds.x !== 'undefined') {
currentBounds.x = bounds.x;
}
if (typeof bounds.y !== 'undefined') {
currentBounds.y = bounds.y;
}
if (typeof bounds.width !== 'undefined') {
currentBounds.width = bounds.width;
}
if (typeof bounds.height !== 'undefined') {
currentBounds.height = bounds.height;
}
annotator.osda.viewer.drawer.viewport.fitBounds(currentBounds);
}
// animate to the annotation
$('html,body').animate({
scrollTop: $(annotator.osda.viewer.element).offset().top
}, 'slow');
}
}
waitingOsda();
}
} else { // It is a text
var hasRanges = typeof an.ranges !== 'undefined' && typeof an.ranges[0] !== 'undefined';
var startOffset = hasRanges ? an.ranges[0].startOffset : '';
var endOffset = hasRanges ? an.ranges[0].endOffset : '';
if (typeof startOffset !== 'undefined' && typeof endOffset !== 'undefined') {
// change the color
$(an.highlights).addClass('api');
// animate to the annotation
$('html,body').animate({
scrollTop: $(an.highlights[0]).offset().top
}, 'slow');
}
}
}
}
} else if (parseInt(API.method, 10) === 2) {
if (typeof mplayer !== 'undefined') {
// variable for Video
var container = decodeURIComponent(API.container);
var player = mplayer[container];
var isVideo = (typeof player !== 'undefined' && container === player.id_);
var isNumber = (!isNaN(parseFloat(API.start)) && isFinite(API.start) && !isNaN(parseFloat(API.end)) && isFinite(API.end));
var isSource = false;
if (isVideo) {
// Compare without extension
var src = decodeURIComponent(API.src);
var targetSrc = src.substring(0, src.lastIndexOf("."));
var playerSrc = (player.tech.options_.source.src === '') ? player.tag.currentSrc : player.tech.options_.source.src;
playerSrc = playerSrc.substring(0, playerSrc.lastIndexOf("."));
isSource = (targetSrc === playerSrc);
}
// Open Video Annotation
if (isVideo && isNumber && isSource) {
var annotation = {
rangeTime: {
start: API.start,
end: API.end
},
created: new Date().toISOString(),
updated: new Date().toISOString(),
target: {
container: container,
src: src
},
media: 'video',
text: decodeURIComponent(API.text),
user: decodeURIComponent(API.user)
};
videojs(player.id_).ready(function(){
if (player.techName !== 'Youtube'){
player.preload('auto');
}
player.autoPlayAPI = annotation;
player.play();
});
}
}
// variable for text
var startOffset = API.startOffset;
var endOffset = API.endOffset;
// Text Annotation
if (!isVideo && typeof startOffset !== 'undefined' && typeof endOffset !== 'undefined') {
var annotation = {
ranges: [{
start: decodeURIComponent(API.start),
end: decodeURIComponent(API.end),
startOffset: decodeURIComponent(API.startOffset),
endOffset: decodeURIComponent(API.endOffset),
}],
created: new Date().toISOString(),
updated: new Date().toISOString(),
media: 'text',
text: decodeURIComponent(API.text),
user: decodeURIComponent(API.user)
};
// show the annotation
annotator.setupAnnotation(annotation);
// to change the color
$(annotation.highlights).addClass('api');
// animate to the annotation
$('html, body').animate({
scrollTop: $(annotation.highlights[0]).offset().top
}, 'slow');
}
// variables for images
var Left = API.Left;
var Top = API.Top;
var Width = API.Width;
var Height = API.Height;
var leftZoom = API.leftZoom;
var topZoom = API.topZoom;
var widthZoom = API.widthZoom;
var heightZoom = API.heightZoom;
// Image Annotation
if (!isVideo && typeof Left !== 'undefined' && typeof Top !== 'undefined' && typeof Width !== 'undefined' && typeof Height !== 'undefined' && typeof leftZoom !== 'undefined' && typeof topZoom !== 'undefined' && typeof widthZoom !== 'undefined' && typeof heightZoom !== 'undefined') {
var an = {
rangePosition: {
width: parseFloat(decodeURIComponent(API.Width)),
top: parseFloat(decodeURIComponent(API.Top)),
left: parseFloat(decodeURIComponent(API.Left)),
height: parseFloat(decodeURIComponent(API.Height)),
},
bounds: {
width: parseFloat(decodeURIComponent(API.widthZoom)),
x: parseFloat(decodeURIComponent(API.leftZoom)),
y: parseFloat(decodeURIComponent(API.topZoom)),
height: parseFloat(decodeURIComponent(API.heightZoom)),
},
target:{
container: API.container,
src: API.src
},
created: new Date().toISOString(),
updated: new Date().toISOString(),
media: 'image',
text: decodeURIComponent(API.text),
user: decodeURIComponent(API.user)
};
var isOpenViewer = typeof annotator.osda !== "undefined" && typeof annotator.osda.viewer !== "undefined";
function waitingOsda() {
isOpenViewer = typeof annotator.osda !== "undefined" && typeof annotator.osda.viewer !== "undefined";
if (!isOpenViewer) {
setTimeout(waitingOsda, 200);
} else {
// show the annotation
annotator.plugins['Store'].annotations.push(an);
annotator.osda.viewer.annotationInstance.drawRect(an);
// change the color
$(an.highlights).addClass('api');
// change zoom
var currentBounds = annotator.osda.viewer.drawer.viewport.getBounds();
var bounds = typeof an.bounds !== 'undefined' ? an.bounds : {};
if (typeof bounds.x !== 'undefined') {
currentBounds.x = bounds.x;
}
if (typeof bounds.y !== 'undefined') {
currentBounds.y = bounds.y;
}
if (typeof bounds.width !== 'undefined') {
currentBounds.width = bounds.width;
}
if (typeof bounds.height !== 'undefined') {
currentBounds.height = bounds.height;
}
annotator.osda.viewer.drawer.viewport.fitBounds(currentBounds);
// animate to the annotation
$('html,body').animate({
scrollTop: $(annotator.osda.viewer.element).offset().top
}, 'slow');
}
}
waitingOsda();
}
}
}
// Let know to others API that this plugin is loaded
annotator.isShareLoaded = true;
annotator.publish('shareloaded');
}
Share.prototype.runAPI = function(API) {
var self = this;
var func = function(annotations) {
self.runningAPI(annotations, API);
self.annotator.unsubscribe("annotationsLoaded", func);
};
this.annotator
// -- Finished the Annotator DOM
.subscribe("annotationsLoaded", func);
}
Share.prototype._isVideo = function(an) {
// Detect if the annotation is a Open Video Annotation
var an = an || {};
var rt = an.rangeTime;
var isVideo = (typeof an.media !== 'undefined' && an.media === 'video');
var hasContainer = (typeof an.target !== 'undefined' && typeof an.target.container !== 'undefined' );
var isNumber = (typeof rt !== 'undefined' && !isNaN(parseFloat(rt.start)) && isFinite(rt.start) && !isNaN(parseFloat(rt.end)) && isFinite(rt.end));
return (isVideo && hasContainer && isNumber);
}
Share.prototype._isImage = function(annotation) {
var wrapper = $('.annotator-wrapper').parent()[0];
var annotator = window.annotator = $.data(wrapper, 'annotator');
var rp = an.rangePosition;
var isOpenSeaDragon = (typeof annotator.osda !== 'undefined');
var isContainer = (typeof an.target !== 'undefined' && typeof an.target.container !== 'undefined');
var isImage = (typeof an.media !== 'undefined' && an.media === 'image');
var isRP = (typeof rp !== 'undefined');
return (isOpenSeaDragon && isContainer && isImage && isRP);
}
Share.prototype.getParameterByName = function(name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
var results = regex.exec('?' + window.location.href.split('?')[1]);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
};
Share.prototype.removeVariableFromURL = function(url_string, variable_name) {
var URL = String(url_string);
var regex = new RegExp( "\\?" + variable_name + "=[^&]*&?", "gi");
URL = URL.replace(regex,'?');
regex = new RegExp( "\\&" + variable_name + "=[^&]*&?", "gi");
URL = URL.replace(regex,'&');
URL = URL.replace(/(\?|&)$/,'');
regex = null;
return URL;
}
Share.prototype.updateViewer = function(field, annotation) {
this.annotation = annotation;
var self = this;
var field = $(field);
var ret = field.addClass('share-viewer-annotator').html(function() {
var string;
return self.buildHTMLShareButton('Share:', self.getSource('ovaId'));
});
// Create the actions for the buttons
this.buttonsActions(field[0], 1, this.options.baseUrl); // 1 is the method of the API that will be for share some annotation in the database
return ret;
};
return Share;
})(Annotator.Plugin);

View File

@@ -1 +0,0 @@
.mce-object{border:1px dotted #3a3a3a;background:#d5d5d5 url(img/object.gif) no-repeat center}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px!important;height:9px!important;border:1px dotted #3a3a3a;background:#d5d5d5 url(img/anchor.gif) no-repeat center}.mce-nbsp{background:#AAA}hr{cursor:default}.mce-match-marker{background:green;color:#fff}.mce-spellchecker-word{background:url(img/wline.gif) repeat-x bottom left;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td.mce-item-selected,th.mce-item-selected{background-color:#39f!important}.mce-edit-focus{outline:1px dotted #333}

View File

@@ -1 +0,0 @@
body{background-color:#fff;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px;scrollbar-3dlight-color:#f0f0ee;scrollbar-arrow-color:#676662;scrollbar-base-color:#f0f0ee;scrollbar-darkshadow-color:#ddd;scrollbar-face-color:#e0e0dd;scrollbar-highlight-color:#f0f0ee;scrollbar-shadow-color:#f0f0ee;scrollbar-track-color:#f5f5f5}td,th{font-family:Verdana,Arial,Helvetica,sans-serif;font-size:11px}.mce-object{border:1px dotted #3a3a3a;background:#d5d5d5 url(img/object.gif) no-repeat center}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px!important;height:9px!important;border:1px dotted #3a3a3a;background:#d5d5d5 url(img/anchor.gif) no-repeat center}.mce-nbsp{background:#AAA}hr{cursor:default}.mce-match-marker{background:green;color:#fff}.mce-spellchecker-word{background:url(img/wline.gif) repeat-x bottom left;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td.mce-item-selected,th.mce-item-selected{background-color:#39f!important}.mce-edit-focus{outline:1px dotted #333}

View File

@@ -1,175 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>
This is a custom SVG font generated by IcoMoon.
<iconset grid="16"></iconset>
</metadata>
<defs>
<font id="icomoon-small" horiz-adv-x="512" >
<font-face units-per-em="512" ascent="480" descent="-32" />
<missing-glyph horiz-adv-x="512" />
<glyph class="hidden" unicode="&#xf000;" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" />
<glyph unicode="&#xe020;" d="M 352,64l0,18.502 c 75.674,30.814, 128,96.91, 128,173.498c0,106.039-100.288,192-224,192S 32,362.039, 32,256
c0-76.588, 52.327-142.684, 128-173.498L 160,64 L 64,64 l-32,48l0-112 l 160,0 L 192,111.406 c-50.45,25.681-85.333,80.77-85.333,144.594
c0,88.366, 66.859,160, 149.333,160c 82.474,0, 149.333-71.634, 149.333-160c0-63.824-34.883-118.913-85.333-144.594L 320,0 l 160,0 L 480,112 l-32-48
L 352,64 z" />
<glyph unicode="&#xe013;" d="M 128,448l0-448 l 128,128l 128-128L 384,448 L 128,448 z M 352,85.255l-96,96l-96-96L 160,416 l 192,0 L 352,85.255 z" />
<glyph unicode="&#xe012;" d="M 463.637,364.892l-66.745,66.744C 386.34,442.188, 372.276,448, 357.293,448s-29.047-5.812-39.598-16.363l-82.746-82.745
c-21.834-21.834-21.834-57.362,0-79.196l 1.373-1.373l 33.941,33.941l-1.373,1.373c-3.066,3.066-3.066,8.247,0,11.313l 82.746,82.746
C 353.641,399.7, 356.040,400, 357.292,400s 3.651-0.299, 5.656-2.305l 66.745-66.744c 3.066-3.067, 3.066-8.249, 0.001-11.314l-82.747-82.747
c-2.004-2.004-4.403-2.304-5.655-2.304s-3.651,0.3-5.656,2.306l-1.373,1.373l-33.94-33.942l 1.371-1.371
c 10.553-10.554, 24.615-16.364, 39.6-16.364s 29.047,5.812, 39.598,16.363l 82.747,82.746C 485.47,307.53, 485.47,343.057, 463.637,364.892
zM 275.678,179.678l-33.941-33.941l 1.373-1.373c 2.004-2.004, 2.305-4.403, 2.305-5.655c0-1.253-0.299-3.651-2.303-5.657
l-82.747-82.745c-2.005-2.005-4.405-2.305-5.657-2.305s-3.652,0.3-5.657,2.305L 82.305,117.050C 80.3,119.055, 80,121.455, 80,122.707
s 0.299,3.65, 2.305,5.656l 82.745,82.744c 2.005,2.006, 4.405,2.306, 5.657,2.306s 3.652-0.3, 5.657-2.306l 1.373-1.371l 33.941,33.94
l-1.373,1.373c-10.552,10.552-24.615,16.363-39.598,16.363s-29.046-5.812-39.598-16.363l-82.744-82.743
C 37.812,151.754, 32,137.689, 32,122.707s 5.812-29.047, 16.363-39.599l 66.745-66.745C 125.661,5.812, 139.724,0, 154.707,0
s 29.046,5.812, 39.598,16.363l 82.747,82.746c 10.552,10.552, 16.361,24.615, 16.361,39.598s-5.812,29.047-16.363,39.598
L 275.678,179.678zM 400,61c-4.862,0-9.725,1.854-13.435,5.565l-64,63.999c-7.422,7.42-7.422,19.449,0,26.869
c 7.42,7.422, 19.448,7.422, 26.868,0l 64-64c 7.422-7.42, 7.422-19.448,0-26.868C 409.725,62.854, 404.862,61, 400,61zM 304,0c-8.837,0-16,7.163-16,16l0,64 c0,8.837, 7.163,16, 16,16s 16-7.163, 16-16l0-64 C 320,7.163, 312.837,0, 304,0zM 464,160l-64,0 c-8.837,0-16,7.163-16,16s 7.163,16, 16,16l 64,0 c 8.837,0, 16-7.163, 16-16S 472.837,160, 464,160zM 112,387c 4.862,0, 9.725-1.854, 13.435-5.565l 64-64c 7.421-7.42, 7.421-19.449,0-26.869c-7.42-7.422-19.449-7.422-26.869,0
l-64,64c-7.421,7.42-7.421,19.449,0,26.869C 102.275,385.146, 107.138,387, 112,387zM 208,448c 8.837,0, 16-7.163, 16-16l0-64 c0-8.837-7.163-16-16-16s-16,7.163-16,16L 192,432 C 192,440.837, 199.163,448, 208,448zM 48,288l 64,0 c 8.837,0, 16-7.163, 16-16s-7.163-16-16-16L 48,256 c-8.837,0-16,7.163-16,16S 39.163,288, 48,288z" />
<glyph unicode="&#xe011;" d="M 463.637,364.892l-66.745,66.744C 386.34,442.188, 372.276,448, 357.293,448s-29.047-5.812-39.598-16.363l-82.746-82.745
c-21.834-21.834-21.834-57.362,0-79.196l 1.373-1.373l 33.941,33.941l-1.373,1.373c-3.066,3.066-3.066,8.247,0,11.313l 82.746,82.746
C 353.641,399.7, 356.040,400, 357.292,400s 3.651-0.299, 5.656-2.305l 66.745-66.744c 3.066-3.067, 3.066-8.249, 0.001-11.314l-82.747-82.747
c-2.004-2.004-4.403-2.304-5.655-2.304s-3.651,0.3-5.656,2.306l-1.373,1.373l-33.94-33.942l 1.371-1.371
c 10.553-10.554, 24.615-16.364, 39.6-16.364s 29.047,5.812, 39.598,16.363l 82.747,82.746C 485.47,307.53, 485.47,343.057, 463.637,364.892
zM 275.678,179.678l-33.941-33.941l 1.373-1.373c 2.004-2.004, 2.305-4.403, 2.305-5.655c0-1.253-0.299-3.651-2.303-5.657
l-82.747-82.745c-2.005-2.005-4.405-2.305-5.657-2.305s-3.652,0.3-5.657,2.305L 82.305,117.050C 80.3,119.055, 80,121.455, 80,122.707
s 0.299,3.65, 2.305,5.656l 82.745,82.744c 2.005,2.006, 4.405,2.306, 5.657,2.306s 3.652-0.3, 5.657-2.306l 1.373-1.371l 33.941,33.94
l-1.373,1.373c-10.552,10.552-24.615,16.363-39.598,16.363s-29.046-5.812-39.598-16.363l-82.744-82.743
C 37.812,151.754, 32,137.689, 32,122.707s 5.812-29.047, 16.363-39.599l 66.745-66.745C 125.661,5.812, 139.724,0, 154.707,0
s 29.046,5.812, 39.598,16.363l 82.747,82.746c 10.552,10.552, 16.361,24.615, 16.361,39.598s-5.812,29.047-16.363,39.598
L 275.678,179.678zM 176,125c-4.862,0-9.725,1.855-13.435,5.564c-7.42,7.42-7.42,19.449,0,26.869l 160,160c 7.42,7.42, 19.448,7.42, 26.868,0
c 7.422-7.42, 7.422-19.45,0-26.87l-160-160C 185.725,126.855, 180.862,125, 176,125z" />
<glyph unicode="&#xe010;" d="M 288,339.337L 288,448 l 168.001-168L 288,112L 288,223.048 C 92.547,227.633, 130.5,99.5, 160,0C 16,160, 53.954,345.437, 288,339.337z" />
<glyph unicode="&#xe00f;" d="M 352,0c 29.5,99.5, 67.453,227.633-128,223.048L 224,112 L 55.999,280L 224,448l0-108.663 C 458.046,345.437, 496,160, 352,0z" />
<glyph unicode="&#xe00e;" d="M 128.214,267.637c 52.9,0, 95.786-45.585, 95.786-101.819C 224,109.586, 181.114,64, 128.214,64
c-52.901,0-95.786,45.585-95.786,101.818L 32,180.364C 32,292.829, 117.77,384, 223.572,384l0-58.182 c-36.55,0-70.913-15.13-96.758-42.602
c-4.977-5.289-9.517-10.917-13.612-16.828C 118.094,267.208, 123.105,267.637, 128.214,267.637zM 384.214,267.637c 52.9,0, 95.786-45.585, 95.786-101.819C 480,109.586, 437.114,64, 384.214,64
c-52.901,0-95.786,45.585-95.786,101.818L 288,180.364C 288,292.829, 373.77,384, 479.572,384l0-58.182 c-36.55,0-70.913-15.13-96.758-42.602
c-4.978-5.289-9.518-10.917-13.612-16.828C 374.094,267.208, 379.105,267.637, 384.214,267.637z" />
<glyph unicode="&#xe00c;" d="M 32,384L 480,384L 480,320L 32,320zM 192,192L 480,192L 480,128L 192,128zM 192,288L 480,288L 480,224L 192,224zM 32,96L 480,96L 480,32L 32,32zM 32,288L 144,208L 32,128 z" />
<glyph unicode="&#xe00d;" d="M 32,384L 480,384L 480,320L 32,320zM 32,192L 320,192L 320,128L 32,128zM 32,288L 320,288L 320,224L 32,224zM 32,96L 480,96L 480,32L 32,32zM 480,288L 368,208L 480,128 z" />
<glyph unicode="&#xe00b;" d="M 192,416L 480,416L 480,352L 192,352zM 192,256L 480,256L 480,192L 192,192zM 192,96L 480,96L 480,32L 192,32zM 160,215L 160,288L 128,288L 128,448L 64,448L 64,416L 96,416L 96,288L 64,288L 64,256L 128,256L 128,231L 64,201L 64,128L 128,128L 128,96L 64,96L 64,64L 128,64L 128,32L 64,32L 64,0L 160,0L 160,160L 96,160L 96,185 z" />
<glyph unicode="&#xe00a;" d="M 192,416L 480,416L 480,352L 192,352zM 192,256L 480,256L 480,192L 192,192zM 192,96L 480,96L 480,32L 192,32zM 64,384A32,32 1980 1 1 128,384A32,32 1980 1 1 64,384zM 64,224A32,32 1980 1 1 128,224A32,32 1980 1 1 64,224zM 64,64A32,32 1980 1 1 128,64A32,32 1980 1 1 64,64z" />
<glyph unicode="&#xe009;" d="M 444,288l-28,0 L 416,416 l 32,0 L 448,448 L 288,448 l0-32 l 32,0 l0-128 L 192,288 L 192,416 l 32,0 L 224,448 L 64,448 l0-32 l 32,0 l0-128 L 68,288 c-19.8,0-36-16.2-36-36l0-216 c0-19.8, 16.2-36, 36-36l 120,0
c 19.8,0, 36,16.2, 36,36L 224,192 l 64,0 l0-156 c0-19.8, 16.2-36, 36-36l 120,0 c 19.8,0, 36,16.2, 36,36L 480,252 C 480,271.8, 463.8,288, 444,288z M 174,32L 82,32
c-9.9,0-18,7.2-18,16s 8.1,16, 18,16l 92,0 c 9.9,0, 18-7.2, 18-16S 183.9,32, 174,32z M 272,224l-32,0 c-8.8,0-16,7.2-16,16s 7.2,16, 16,16l 32,0
c 8.8,0, 16-7.2, 16-16S 280.8,224, 272,224z M 430,32l-92,0 c-9.9,0-18,7.2-18,16s 8.1,16, 18,16l 92,0 c 9.9,0, 18-7.2, 18-16S 439.9,32, 430,32z" />
<glyph unicode="&#xe008;" d="M 352,288l0,80 c0,8.8-7.2,16-16,16l-80,0 L 256,416 c0,17.6-14.4,32-32,32l-64,0 c-17.602,0-32-14.4-32-32l0-32 L 48,384 c-8.801,0-16-7.2-16-16l0-256
c0-8.8, 7.199-16, 16-16l 112,0 l0-96 l 192,0 l 96,96L 448,288 L 352,288 z M 160,415.943c 0.017,0.019, 0.036,0.039, 0.057,0.057l 63.884,0
c 0.021-0.018, 0.041-0.038, 0.059-0.057L 224,384 l-64,0 L 160,415.943 L 160,415.943z M 96,320l0,32 l 192,0 l0-32 L 96,320 z M 352,45.255L 352,96 l 50.745,0 L 352,45.255z
M 416,128l-96,0 l0-96 L 192,32 L 192,256 l 224,0 L 416,128 z" />
<glyph unicode="&#xe031;" d="M 416,320l-96,0 l0,32 l-96,96L 32,448 l0-352 l 192,0 l0-96 l 288,0 L 512,224 L 416,320z M 416,274.745L 466.745,224L 416,224 L 416,274.745 z M 224,402.745L 274.745,352
L 224,352 L 224,402.745 z M 64,416l 128,0 l0-96 l 96,0 l0-192 L 64,128 L 64,416 z M 480,32L 256,32 l0,64 l 64,0 L 320,288 l 64,0 l0-96 l 96,0 L 480,32 z" />
<glyph unicode="&#xe007;" d="M 432.204,144.934c-23.235,23.235-53.469,34.002-80.541,31.403L 320,208l 96,96c0,0, 64,64,0,128L 256,272L 96,432
c-64-64,0-128,0-128l 96-96l-31.663-31.663c-27.072,2.599-57.305-8.169-80.54-31.403c-37.49-37.49-42.556-93.209-11.313-124.45
c 31.241-31.241, 86.96-26.177, 124.45,11.313c 23.235,23.234, 34.001,53.469, 31.403,80.54L 256,144l 31.664-31.664
c-2.598-27.072, 8.168-57.305, 31.403-80.539c 37.489-37.49, 93.209-42.556, 124.449-11.313
C 474.76,51.725, 469.694,107.443, 432.204,144.934z M 176.562,100.711c-1.106-12.166-7.51-24.913-17.57-34.973
C 147.886,54.631, 133.452,48, 120.383,48c-5.262,0-12.649,1.114-17.958,6.424c-10.703,10.702-8.688,36.566, 11.313,56.568
c 11.106,11.107, 25.54,17.738, 38.609,17.738c 5.262,0, 12.649-1.114, 17.958-6.424C 176.861,115.751, 177.040,105.962, 176.562,100.711z
M 256,176c-17.673,0-32,14.327-32,32s 14.327,32, 32,32s 32-14.327, 32-32S 273.673,176, 256,176z M 409.576,54.424
c-5.31-5.31-12.696-6.424-17.958-6.424c-13.069,0-27.503,6.631-38.609,17.738c-10.061,10.060-16.464,22.807-17.569,34.973
c-0.479,5.251-0.3,15.040, 6.257,21.596c 5.309,5.311, 12.695,6.424, 17.958,6.424c 13.068,0, 27.503-6.631, 38.608-17.737
C 418.265,90.99, 420.279,65.126, 409.576,54.424z" />
<glyph unicode="&#xe006;" d="M 32,384L 480,384L 480,320L 32,320zM 32,192L 480,192L 480,128L 32,128zM 32,288L 480,288L 480,224L 32,224zM 32,96L 480,96L 480,32L 32,32z" />
<glyph unicode="&#xe004;" d="M 32,384L 480,384L 480,320L 32,320zM 32,192L 480,192L 480,128L 32,128zM 128,288L 384,288L 384,224L 128,224zM 128,96L 384,96L 384,32L 128,32z" />
<glyph unicode="&#xe005;" d="M 32,384L 480,384L 480,320L 32,320zM 32,192L 480,192L 480,128L 32,128zM 192,288L 480,288L 480,224L 192,224zM 192,96L 480,96L 480,32L 192,32z" />
<glyph unicode="&#xe003;" d="M 32,384L 480,384L 480,320L 32,320zM 32,192L 480,192L 480,128L 32,128zM 32,288L 320,288L 320,224L 32,224zM 32,96L 320,96L 320,32L 32,32z" />
<glyph unicode="&#xe02d;" d="M 480,224l-4.571,0 L 347.062,224 c-25.039,17.71-57.215,27.43-91.062,27.43c-44.603,0-82.286,25.121-82.286,54.856
c0,29.735, 37.683,54.857, 82.286,54.857c 37.529,0, 70.154-17.788, 79.56-41.143l 56.508,0 c-3.965,25.322-18.79,48.984-42.029,66.413
C 324.599,405.493, 291.201,416, 256,416c-35.202,0-68.598-10.507-94.037-29.587c-27.394-20.545-43.106-49.751-43.106-80.127
s 15.712-59.582, 43.106-80.127c 0.978-0.733, 1.971-1.449, 2.973-2.158L 36.571,224.001 L 32,224.001 l0-32 l 256.266,0 c 29.104-8.553, 50.021-28.135, 50.021-50.286
c0-29.734-37.684-54.855-82.286-54.855c-37.53,0-70.154,17.787-79.559,41.143l-56.508,0 c 3.965-25.32, 18.791-48.984, 42.030-66.413
C 187.402,42.508, 220.798,32, 256,32c 35.201,0, 68.599,10.508, 94.037,29.587c 27.395,20.545, 43.104,49.751, 43.104,80.127
c0,17.649-5.327,34.896-15.147,50.286L 480,192 L 480,224 z" />
<glyph unicode="&#xe02c;" d="M 96,64l 288,0 l0-32 L 96,32 L 96,64 zM 320,416l0-192 c0-15.656-7.35-30.812-20.695-42.676C 283.834,167.573, 262.771,160, 240,160c-22.772,0-43.834,7.573-59.304,21.324
C 167.35,193.188, 160,208.344, 160,224L 160,416 L 96,416 l0-192 c0-70.691, 64.471-128, 144-128c 79.529,0, 144,57.309, 144,128L 384,416 L 320,416 z" />
<glyph unicode="&#xe02b;" d="M 416,416l0-32 l-72,0 L 216,64l 72,0 l0-32 L 64,32 l0,32 l 72,0 L 264,384l-72,0 L 192,416 L 416,416 z" />
<glyph unicode="&#xe02a;" d="M 312.721,232.909C 336.758,251.984, 352,280.337, 352,312c0,57.438-50.145,104-112,104L 128,416 l0-384 l 144,0
c 61.856,0, 112,46.562, 112,104C 384,180.098, 354.441,217.781, 312.721,232.909z M 192,328c0,13.255, 10.745,24, 24,24l 33.602,0
C 270.809,352, 288,330.51, 288,304s-17.191-48-38.398-48L 192,256 L 192,328 z M 273.6,96L 216,96 c-13.255,0-24,10.745-24,24l0,72 l 81.6,0
c 21.209,0, 38.4-21.49, 38.4-48S 294.809,96, 273.6,96z" />
<glyph unicode="&#xe001;" d="M 425.373,358.627l-66.746,66.745C 346.183,437.818, 321.6,448, 304,448L 96,448 c-17.6,0-32-14.4-32-32l0-384 c0-17.6, 14.4-32, 32-32l 320,0
c 17.6,0, 32,14.4, 32,32L 448,304 C 448,321.6, 437.817,346.182, 425.373,358.627z M 402.745,336.001c 3.396-3.398, 6.896-9.581, 9.447-16.001L 320,320
L 320,412.193 c 6.42-2.55, 12.602-6.050, 16-9.448L 402.745,336.001z M 415.942,32L 96.057,32 c-0.020,0.017-0.041,0.038-0.057,0.058L 96,415.943
c 0.017,0.020, 0.038,0.041, 0.057,0.057L 288,416 l0-128 l 128,0 l0-255.942 C 415.983,32.038, 415.962,32.017, 415.942,32z" />
<glyph unicode="&#xe000;" d="M 480,40L 480,335.969 L 368.031,448L 72,448 c-22.091,0-40-17.908-40-40l0-368 c0-22.092, 17.909-40, 40-40l 368,0
C 462.092,0, 480,17.908, 480,40z M 288,384l 32,0 l0-96 l-32,0 L 288,384 z M 352,64L 160,64 L 160,191.941 c 0.017,0.021, 0.038,0.041, 0.058,0.059l 191.885,0
c 0.020-0.018, 0.041-0.038, 0.058-0.059L 352,64L 352,64z M 416,64l-32,0 L 384,192 c0,17.6-14.4,32-32,32L 160,224 c-17.6,0-32-14.4-32-32l0-128 L 96,64 L 96,384
l 32,0 l0-96 c0-17.6, 14.4-32, 32-32l 160,0 c 17.6,0, 32,14.4, 32,32l0,85.505 l 64-64.036L 416,64 z" />
<glyph unicode="&#xe01b;" d="M 32,384l0-352 l 448,0 L 480,384 L 32,384 z M 192,160l0,64 l 128,0 l0-64 L 192,160 z M 320,128l0-64 L 192,64 l0,64 L 320,128 z M 320,320l0-64 L 192,256 l0,64 L 320,320 z M 160,320l0-64 L 64,256 l0,64 L 160,320
z M 64,224l 96,0 l0-64 L 64,160 L 64,224 z M 352,224l 96,0 l0-64 l-96,0 L 352,224 z M 352,256l0,64 l 96,0 l0-64 L 352,256 z M 64,128l 96,0 l0-64 L 64,64 L 64,128 z M 352,64l0,64 l 96,0 l0-64 L 352,64 z" />
<glyph unicode="&#xe021;" d="M 256,410c 49.683,0, 96.391-19.347, 131.521-54.478S 442,273.683, 442,224s-19.348-96.391-54.479-131.521S 305.683,38, 256,38
s-96.391,19.348-131.522,54.479S 70,174.317, 70,224s 19.347,96.391, 54.478,131.522S 206.317,410, 256,410 M 256,448
C 132.288,448, 32,347.712, 32,224s 100.288-224, 224-224s 224,100.288, 224,224S 379.712,448, 256,448L 256,448zM 160,288A32,32 1980 1 1 224,288A32,32 1980 1 1 160,288zM 288,288A32,32 1980 1 1 352,288A32,32 1980 1 1 288,288zM 256,152c-50.92,0-96.28,18.437-125.583,47.164C 141.98,140.36, 193.806,96, 256,96c 62.194,0, 114.020,44.36, 125.584,103.164
C 352.28,170.437, 306.92,152, 256,152z" />
<glyph unicode="&#xe023;" d="M 240,288L 144,384L 208,448L 32,448L 32,272L 96,336L 192,240 zM 320,240L 416,336L 480,272L 480,448L 304,448L 368,384L 272,288 zM 272,160L 368,64L 304,0L 480,0L 480,176L 416,112L 320,208 zM 192,208L 96,112L 32,176L 32,0L 208,0L 144,64L 240,160 z" />
<glyph unicode="&#xe01c;" d="M 32,256L 480,256L 480,192L 32,192z" />
<glyph unicode="&#xe01d;" d="M 32,96l 256,0 l0-64 L 32,32 L 32,96 z M 384,384L 273.721,384 l-91.883-256l-66.144,0 l 91.881,256L 96,384 L 96,448 l 288,0 L 384,384 z M 464.887,32L 400,96.887
L 335.113,32L 304,63.113L 368.887,128L 304,192.887L 335.113,224L 400,159.113L 464.887,224L 496,192.887L 431.113,128L 496,63.113
L 464.887,32z" />
<glyph unicode="&#xe022;" d="M 128,416l 256,0 l0-64 L 128,352 L 128,416 z M 448,320L 64,320 c-17.6,0-32-14.4-32-32l0-128 c0-17.6, 14.398-32, 32-32l 64,0 l0-96 l 256,0 l0,96 l 64,0
c 17.6,0, 32,14.4, 32,32L 480,288 C 480,305.6, 465.6,320, 448,320z M 352,64L 160,64 L 160,192 l 192,0 L 352,64 z M 455.2,272c0-12.813-10.387-23.2-23.199-23.2
S 408.8,259.187, 408.8,272s 10.389,23.2, 23.201,23.2C 444.814,295.2, 455.2,284.813, 455.2,272z" />
<glyph unicode="&#xe02e;" d="M 192,416c-61.856,0-112-50.144-112-112s 50.144-112, 112-112l0-160 l 64,0 L 256,352 l 32,0 l0-320 l 64,0 L 352,352 l 64,0 L 416,416 L 192,416 z" />
<glyph unicode="&#xe02f;" d="M 224,416c-61.856,0-112-50.144-112-112s 50.144-112, 112-112l0-160 l 64,0 L 288,352 l 32,0 l0-320 l 64,0 L 384,352 l 64,0 L 448,416 L 224,416 zM 32,32L 144,128L 32,224 z" />
<glyph unicode="&#xe030;" d="M 160,416C 98.144,416, 48,365.856, 48,304s 50.144-112, 112-112l0-160 l 64,0 L 224,352 l 32,0 l0-320 l 64,0 L 320,352 l 64,0 L 384,416 L 160,416 zM 480,224L 368,128L 480,32 z" />
<glyph unicode="&#xe026;" d="M 256,288L 320,288L 320,256L 256,256zM 256,96L 320,96L 320,64L 256,64zM 288,192L 352,192L 352,160L 288,160zM 384,192L 384,96L 352,96L 352,64L 416,64L 416,192 zM 192,192L 256,192L 256,160L 192,160zM 160,96L 224,96L 224,64L 160,64zM 160,288L 224,288L 224,256L 160,256zM 96,384L 96,256L 128,256L 128,352L 160,352L 160,384 zM 352,256L 416,256L 416,384L 384,384L 384,288L 352,288 zM 32,448l0-448 l 448,0 L 480,448 L 32,448 z M 448,32L 64,32 L 64,416 l 384,0 L 448,32 zM 96,192L 96,64L 128,64L 128,160L 160,160L 160,192 zM 288,384L 352,384L 352,352L 288,352zM 192,384L 256,384L 256,352L 192,352z" />
<glyph unicode="&#xe027;" d="M 408,448l 8-192L 96,256 l 8,192l 16,0 l 8-160l 256,0 l 8,160L 408,448 z M 104,0l-8,160l 320,0 l-8-160l-16,0 l-8,128L 128,128 l-8-128L 104,0 zM 32,224L 96,224L 96,192L 32,192zM 128,224L 192,224L 192,192L 128,192zM 224,224L 288,224L 288,192L 224,192zM 320,224L 384,224L 384,192L 320,192zM 416,224L 480,224L 480,192L 416,192z" />
<glyph unicode="&#xe024;" d="M 480,416L 480,448 l-96,0 c-17.601,0-32-14.4-32-32l0-160 c0-7.928, 2.929-15.201, 7.748-20.807L 208,105l-71,74l-41-35l 112-144l 208,224l 64,0
l0,32 l-96,0 L 384,416 L 480,416 zM 128,224l 32,0 L 160,416 c0,17.6-14.4,32-32,32L 64,448 c-17.6,0-32-14.4-32-32l0-192 l 32,0 l0,96 l 64,0 L 128,224 z M 64,352L 64,416 l 64,0 l0-64 L 64,352 zM 320,256l0,48 c0,17.6-4.4,32-22,32c 17.6,0, 22,14.4, 22,32L 320,416 c0,17.6-14.4,32-32,32l-96,0 l0-224 l 96,0 C 305.6,224, 320,238.4, 320,256z
M 224,416l 64,0 l0-64 l-64,0 L 224,416 z M 224,320l 64,0 l0-64 l-64,0 L 224,320 z" />
<glyph unicode="&#xe025;" d="M 224,224l-64,0 l0,64 l 64,0 l0,64 l 64,0 l0-64 l 64,0 l0-64 l-64,0 l0-64 l-64,0 L 224,224 z M 480,192l0-160 L 32,32 L 32,192 l 64,0 l0-96 l 320,0 l0,96 L 480,192 z" />
<glyph unicode="&#xe017;" d="M 208,128L 112,224L 208,320L 176,352L 48,224L 176,96 zM 336,352L 304,320L 400,224L 304,128L 336,96L 464,224 z" />
<glyph unicode="&#xe016;" d="M 224,128l 64,0 l0-64 l-64,0 L 224,128 z M 352,352c 17.673,0, 32-14.327, 32-32l0-83 l-114-77l-46,0 l0,32 l 96,64l0,32 L 160,288 l0,64 L 352,352 z M 256,448
c-59.833,0-116.083-23.3-158.392-65.608C 55.301,340.083, 32,283.833, 32,224c0-59.832, 23.301-116.084, 65.608-158.392
C 139.917,23.3, 196.167,0, 256,0c 59.832,0, 116.084,23.3, 158.392,65.608C 456.7,107.916, 480,164.168, 480,224
c0,59.833-23.3,116.083-65.608,158.392C 372.084,424.7, 315.832,448, 256,448z" />
<glyph unicode="&#xe014;" d="M 448,416L 64,416 c-17.6,0-32-14.4-32-32l0-320 c0-17.6, 14.4-32, 32-32l 384,0 c 17.6,0, 32,14.4, 32,32L 480,384 C 480,401.6, 465.6,416, 448,416z
M 448,64.058c-0.006-0.007-0.015-0.014-0.021-0.021L 352,224l-80-64L 160,304L 64.016,64.042c-0.005,0.005-0.011,0.011-0.016,0.016
L 64,383.943 c 0.017,0.020, 0.038,0.041, 0.057,0.057l 383.885,0 c 0.020-0.017, 0.041-0.038, 0.058-0.058L 448,64.058 zM 320,304A48,48 1980 1 1 416,304A48,48 1980 1 1 320,304z" />
<glyph unicode="&#xe015;" d="M 448,416L 64,416 c-17.6,0-32-14.4-32-32l0-320 c0-17.6, 14.4-32, 32-32l 384,0 c 17.6,0, 32,14.4, 32,32L 480,384 C 480,401.6, 465.6,416, 448,416z
M 128,64L 64,64 l0,64 l 64,0 L 128,64 z M 128,192L 64,192 l0,64 l 64,0 L 128,192 z M 128,320L 64,320 L 64,384 l 64,0 L 128,320 z M 352,64L 160,64 L 160,384 l 192,0 L 352,64 z M 448,64l-64,0 l0,64 l 64,0 L 448,64 z
M 448,192l-64,0 l0,64 l 64,0 L 448,192 z M 448,320l-64,0 L 384,384 l 64,0 L 448,320 zM 192,320L 192,128L 336,224 z" />
<glyph unicode="&#xe018;" d="M 38.899,327.688l 40.707-25.441C 105.007,342.804, 144,373.974, 190.21,389.37l-15.183,45.547
C 118.153,415.968, 70.163,377.604, 38.899,327.688zM 336.973,434.917L 321.79,389.37c 46.211-15.396, 85.202-46.566, 110.604-87.124l 40.706,25.441
C 441.837,377.604, 393.847,415.968, 336.973,434.917zM 303.987,127.996c-2.404,0-4.846,0.545-7.143,1.693L 224,166.111L 224,272 c0,8.836, 7.164,16, 16,16s 16-7.164, 16-16l0-86.111
l 55.155-27.578c 7.903-3.951, 11.107-13.562, 7.155-21.466C 315.508,131.238, 309.856,127.997, 303.987,127.996zM 256,384C 149.961,384, 64,298.039, 64,192c0-106.039, 85.961-192, 192-192c 106.039,0, 192,85.961, 192,192
C 448,298.039, 362.039,384, 256,384z M 256,48c-79.529,0-144,64.471-144,144c0,79.529, 64.471,144, 144,144c 79.529,0, 144-64.471, 144-144
C 400,112.471, 335.529,48, 256,48z" />
<glyph unicode="&#xe019;" d="M 32,252.127c 22.659,24.96, 48.581,46.18, 76.636,62.562C 153.802,341.061, 204.759,355, 256,355
c 51.24,0, 102.198-13.939, 147.363-40.312c 28.056-16.382, 53.978-37.602, 76.637-62.562l0,58.716
c-16.505,14.059-34.062,26.57-52.434,37.297C 375.063,378.796, 315.737,395, 256,395s-119.064-16.204-171.567-46.86
C 66.062,337.413, 48.505,324.901, 32,310.842L 32,252.127 zM 256,320c-91.598,0-172.919-50.278-224-128c 51.081-77.724, 132.402-128, 224-128c 91.598,0, 172.919,50.276, 224,128
C 428.919,269.722, 347.598,320, 256,320z M 256,224c0-17.673-14.327-32-32-32s-32,14.327-32,32c0,17.674, 14.327,32, 32,32
S 256,241.674, 256,224z M 364.033,131.669C 330.316,111.982, 293.969,102, 256,102s-74.316,9.982-108.033,29.669
C 122.19,146.721, 98.659,167.324, 78.91,192c 19.749,24.675, 43.28,45.279, 69.058,60.33c 6.638,3.876, 13.379,7.37, 20.213,10.491
C 162.925,250.95, 160,237.817, 160,224c0-53.020, 42.981-96, 96-96c 53.020,0, 96,42.98, 96,96c0,13.817-2.925,26.95-8.18,38.821
c 6.834-3.122, 13.575-6.615, 20.213-10.491c 25.777-15.051, 49.308-35.655, 69.058-60.33
C 413.342,167.324, 389.811,146.721, 364.033,131.669z" />
<glyph unicode="&#xe01a;" d="M 325.584,338.083C 313.278,379.064, 311.146,384, 272,384l-32,0 c-39.809,0-41.332-5.076-54.209-48c0-0.001,0-0.001-0.001-0.002
L 113.791,96l 56.818,0 l 28.8,96l 113.183,0 l 28.8-96l 56.815,0 L 325.584,338.083z M 218.609,256l 19.2,68c 5.043,16.809, 18.19,15, 18.19,15
s 13.147,1.809, 18.19-15l 0.002,0 l 19.2-68L 218.609,256 z" />
<glyph unicode="&#xe028;" d="M 288,448 C 411.712,448 512,347.712 512,224 C 512,100.288 411.712,0 288,0 L 288,48 C 335.012,48 379.209,66.307 412.451,99.549 C 445.693,132.791 464,176.988 464,224 C 464,271.011 445.693,315.209 412.451,348.451 C 379.209,381.693 335.012,400 288,400 C 240.989,400 196.791,381.693 163.549,348.451 C 137.979,322.882 121.258,290.828 114.896,256 L 208,256 L 96,128 L -16,256 L 66.285,256 C 81.815,364.551 175.154,448 288,448 ZM 384,256 L 384,192 L 256,192 L 256,352 L 320,352 L 320,256 Z" />
<glyph unicode="&#xe002;" d="M 512,183.771l0,80.458 l-79.572,7.957c-4.093,15.021-10.044,29.274-17.605,42.49l 52.298,63.919L 410.595,435.12l-63.918-52.298
c-13.217,7.562-27.471,13.513-42.491,17.604L 296.229,480l-80.458,0 l-7.957-79.573c-15.021-4.093-29.274-10.043-42.49-17.604
L 101.405,435.12L 44.88,378.595l 52.298-63.918c-7.562-13.216-13.513-27.47-17.605-42.49L0,264.229l0-80.458 l 79.573-7.957
c 4.093-15.021, 10.043-29.274, 17.605-42.491L 44.88,69.405l 56.524-56.524l 63.919,52.298c 13.216-7.562, 27.47-13.514, 42.49-17.605
L 215.771-32l 80.458,0 l 7.957,79.572c 15.021,4.093, 29.274,10.044, 42.491,17.605l 63.918-52.298l 56.524,56.524l-52.298,63.918
c 7.562,13.217, 13.514,27.471, 17.605,42.49L 512,183.771z M 352,192l-64-64l-64,0 l-64,64l0,64 l 64,64l 64,0 l 64-64L 352,192 z" />
<glyph unicode="&#xe01f;" d="M 384,377 L 384,352 L 448,352 L 448,320 L 352,320 L 352,393 L 416,423 L 416,448 L 352,448 L 352,480 L 448,480 L 448,407 ZM 338,352L 270,352L 176,258L 82,352L 14,352L 142,224L 14,96L 82,96L 176,190L 270,96L 338,96L 210,224 z" />
<glyph unicode="&#xe01e;" d="M 384,25 L 384,0 L 448,0 L 448-32 L 352-32 L 352,41 L 416,71 L 416,96 L 352,96 L 352,128 L 448,128 L 448,55 ZM 338,352L 270,352L 176,258L 82,352L 14,352L 142,224L 14,96L 82,96L 176,190L 270,96L 338,96L 210,224 z" />
<glyph unicode="&#xe035;" d="M 352,288l0,80 c0,8.8-7.2,16-16,16l-80,0 L 256,416 c0,17.6-14.4,32-32,32l-64,0 c-17.602,0-32-14.4-32-32l0-32 L 48,384 c-8.801,0-16-7.2-16-16
l0-256 c0-8.8, 7.199-16, 16-16l 112,0 l0-96 l 288,0 L 448,288 L 352,288 z M 160,415.943c 0.017,0.019, 0.036,0.039, 0.057,0.057l 63.884,0
c 0.021-0.018, 0.041-0.038, 0.059-0.057L 224,384 l-64,0 L 160,415.943 z M 96,320l0,32 l 192,0 l0-32 L 96,320 z M 416,32L 192,32 L 192,256 l 224,0 L 416,32 zM 224,224L 224,160L 240,160L 256,192L 288,192L 288,96L 264,96L 264,64L 344,64L 344,96L 320,96L 320,192L 352,192L 368,160L 384,160L 384,224 z" />
<glyph unicode="&#xe032;" d="M 384,352L 416,352L 416,320L 384,320zM 320,288L 352,288L 352,256L 320,256zM 320,224L 352,224L 352,192L 320,192zM 320,160L 352,160L 352,128L 320,128zM 256,224L 288,224L 288,192L 256,192zM 256,160L 288,160L 288,128L 256,128zM 192,160L 224,160L 224,128L 192,128zM 384,288L 416,288L 416,256L 384,256zM 384,224L 416,224L 416,192L 384,192zM 384,160L 416,160L 416,128L 384,128zM 384,96L 416,96L 416,64L 384,64zM 320,96L 352,96L 352,64L 320,64zM 256,96L 288,96L 288,64L 256,64zM 192,96L 224,96L 224,64L 192,64zM 128,96L 160,96L 160,64L 128,64z" />
<glyph unicode="&#xe034;" d="M 464,416L 256,416L 240,448L 64,448L 32,384L 480,384 zM 420.17,128L 464,128 l 16,224L 32,352 l 32-320l 178.040,0 C 189.599,50.888, 152,101.133, 152,160c0,74.991, 61.009,136, 136,136
c 74.99,0, 136-61.009, 136-136C 424,149.161, 422.689,138.425, 420.17,128zM 437.498,55.125l-67.248,55.346C 378.977,124.932, 384,141.878, 384,160c0,53.020-42.98,96-96,96s-96-42.98-96-96
s 42.98-96, 96-96c 18.122,0, 35.069,5.023, 49.529,13.75l 55.346-67.248c 11.481-13.339, 31.059-14.070, 43.503-1.626l 2.746,2.746
C 451.568,24.066, 450.837,43.644, 437.498,55.125z M 288,98c-34.242,0-62,27.758-62,62s 27.758,62, 62,62s 62-27.758, 62-62
S 322.242,98, 288,98z" />
<glyph unicode="&#x20;" horiz-adv-x="256" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -1,153 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>
This is a custom SVG font generated by IcoMoon.
<iconset grid="16"></iconset>
</metadata>
<defs>
<font id="icomoon" horiz-adv-x="512" >
<font-face units-per-em="512" ascent="480" descent="-32" />
<missing-glyph horiz-adv-x="512" />
<glyph class="hidden" unicode="&#xf000;" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" />
<glyph unicode="&#xe034;" d="M 464,416L 256,416L 240,448L 64,448L 32,384L 480,384 zM 452.17,128l 37.43,0 L 512,352L0,352 l 32-320l 242.040,0 C 221.599,50.888, 184,101.133, 184,160c0,74.991, 61.009,136, 136,136
c 74.99,0, 136-61.009, 136-136C 456,149.161, 454.689,138.425, 452.17,128zM 501.498,23.125l-99.248,87.346C 410.977,124.931, 416,141.878, 416,160c0,53.020-42.98,96-96,96s-96-42.98-96-96
s 42.98-96, 96-96c 18.122,0, 35.069,5.023, 49.529,13.75l 87.346-99.248c 11.481-13.339, 31.059-14.070, 43.503-1.626l 2.746,2.746
C 515.568-7.934, 514.837,11.644, 501.498,23.125z M 320,98c-34.242,0-62,27.758-62,62s 27.758,62, 62,62s 62-27.758, 62-62
S 354.242,98, 320,98z" />
<glyph unicode="&#xe032;" d="M 384,352L 416,352L 416,320L 384,320zM 320,288L 352,288L 352,256L 320,256zM 320,224L 352,224L 352,192L 320,192zM 320,160L 352,160L 352,128L 320,128zM 256,224L 288,224L 288,192L 256,192zM 256,160L 288,160L 288,128L 256,128zM 192,160L 224,160L 224,128L 192,128zM 384,288L 416,288L 416,256L 384,256zM 384,224L 416,224L 416,192L 384,192zM 384,160L 416,160L 416,128L 384,128zM 384,96L 416,96L 416,64L 384,64zM 320,96L 352,96L 352,64L 320,64zM 256,96L 288,96L 288,64L 256,64zM 192,96L 224,96L 224,64L 192,64zM 128,96L 160,96L 160,64L 128,64z" />
<glyph unicode="&#xe031;" d="M 416,352l-96,0 L 320,384 L 224,480L0,480 l0-384 l 192,0 l0-128 l 320,0 L 512,256 L 416,352z M 416,306.745L 466.745,256L 416,256 L 416,306.745 z M 224,434.745L 274.745,384L 224,384
L 224,434.745 z M 32,448l 160,0 l0-96 l 96,0 l0-224 L 32,128 L 32,448 z M 480,0L 224,0 l0,96 l 96,0 L 320,320 l 64,0 l0-96 l 96,0 L 480,0 z" />
<glyph unicode="&#xe030;" d="M 128,448 L 384,448 L 384,384 L 320,384 L 320,0 L 256,0 L 256,384 L 192,384 L 192,0 L 128,0 L 128,224 C 66.144,224 16,274.144 16,336 C 16,397.856 66.144,448 128,448 ZM 480,32L 352,144L 480,256 z" />
<glyph unicode="&#xe02f;" d="M 224,448 L 480,448 L 480,384 L 416,384 L 416,0 L 352,0 L 352,384 L 288,384 L 288,0 L 224,0 L 224,224 C 162.144,224 112,274.144 112,336 C 112,397.856 162.144,448 224,448 ZM 32,256L 160,144L 32,32 z" />
<glyph unicode="&#xe02e;" d="M 192,448 L 448,448 L 448,384 L 384,384 L 384,0 L 320,0 L 320,384 L 256,384 L 256,0 L 192,0 L 192,224 C 130.144,224 80,274.144 80,336 C 80,397.856 130.144,448 192,448 Z" />
<glyph unicode="&#xe02d;" d="M 365.71,221.482 C 397.67,197.513 416,163.439 416,128 C 416,92.561 397.67,58.487 365.71,34.518 C 336.031,12.259 297.068,0 256,0 C 214.931,0 175.969,12.259 146.29,34.518 C 114.33,58.487 96,92.561 96,128 L 160,128 C 160,93.309 203.963,64 256,64 C 308.037,64 352,93.309 352,128 C 352,162.691 308.037,192 256,192 C 214.931,192 175.969,204.259 146.29,226.518 C 114.33,250.488 96,284.561 96,320 C 96,355.439 114.33,389.512 146.29,413.482 C 175.969,435.741 214.931,448 256,448 C 297.068,448 336.031,435.741 365.71,413.482 C 397.67,389.512 416,355.439 416,320 L 352,320 C 352,354.691 308.037,384 256,384 C 203.963,384 160,354.691 160,320 C 160,285.309 203.963,256 256,256 C 297.068,256 336.031,243.741 365.71,221.482 ZM0,224L 512,224L 512,192L0,192z" />
<glyph unicode="&#xe02c;" d="M 352,448 L 416,448 L 416,240 C 416,160.471 344.366,96 256,96 C 167.635,96 96,160.471 96,240 L 96,448 L 160,448 L 160,240 C 160,219.917 169.119,200.648 185.677,185.747 C 204.125,169.145 229.1,160 256,160 C 282.9,160 307.875,169.145 326.323,185.747 C 342.881,200.648 352,219.917 352,240 L 352,448 ZM 96,64L 416,64L 416,0L 96,0z" />
<glyph unicode="&#xe02b;" d="M 448,448 L 448,416 L 384,416 L 224,32 L 288,32 L 288,0 L 64,0 L 64,32 L 128,32 L 288,416 L 224,416 L 224,448 Z" />
<glyph unicode="&#xe02a;" d="M 353.94,237.674C 372.689,259.945, 384,288.678, 384,320c0,70.58-57.421,128-128,128l-64,0 l-64,0 L 96,448 l0-448 l 32,0 l 64,0 l 96,0
c 70.579,0, 128,57.421, 128,128C 416,174.478, 391.101,215.248, 353.94,237.674z M 192,384l 50.75,0 c 27.984,0, 50.75-28.71, 50.75-64
s-22.766-64-50.75-64L 192,256 L 192,384 z M 271.5,64L 192,64 L 192,192 l 79.5,0 c 29.225,0, 53-28.71, 53-64S 300.725,64, 271.5,64z" />
<glyph unicode="&#xe029;" d="M 192,64L 288,64L 288-32L 192-32zM 400,448 C 426.51,448 448,426.51 448,400 L 448,256 L 288,160 L 288,96 L 192,96 L 192,192 L 352,288 L 352,352 L 96,352 L 96,448 L 400,448 Z" />
<glyph unicode="&#xe028;" d="M 288,448 C 411.712,448 512,347.712 512,224 C 512,100.288 411.712,0 288,0 L 288,48 C 335.012,48 379.209,66.307 412.451,99.549 C 445.693,132.791 464,176.988 464,224 C 464,271.011 445.693,315.209 412.451,348.451 C 379.209,381.693 335.012,400 288,400 C 240.989,400 196.791,381.693 163.549,348.451 C 137.979,322.882 121.258,290.828 114.896,256 L 208,256 L 96,128 L -16,256 L 66.285,256 C 81.815,364.551 175.154,448 288,448 ZM 384,256 L 384,192 L 256,192 L 256,352 L 320,352 L 320,256 Z" />
<glyph unicode="&#xe027;" d="M0,224L 64,224L 64,192L0,192zM 96,224L 192,224L 192,192L 96,192zM 224,224L 288,224L 288,192L 224,192zM 320,224L 416,224L 416,192L 320,192zM 448,224L 512,224L 512,192L 448,192zM 440,480 L 448,256 L 64,256 L 72,480 L 88,480 L 96,288 L 416,288 L 424,480 ZM 72-32 L 64,160 L 448,160 L 440-32 L 424-32 L 416,128 L 96,128 L 88-32 Z" />
<glyph unicode="&#xe026;" d="M 192,384L 256,384L 256,352L 192,352zM 288,384L 352,384L 352,352L 288,352zM 448,384 L 448,256 L 352,256 L 352,288 L 416,288 L 416,352 L 384,352 L 384,384 ZM 160,288L 224,288L 224,256L 160,256zM 256,288L 320,288L 320,256L 256,256zM 96,352 L 96,288 L 128,288 L 128,256 L 64,256 L 64,384 L 160,384 L 160,352 ZM 192,192L 256,192L 256,160L 192,160zM 288,192L 352,192L 352,160L 288,160zM 448,192 L 448,64 L 352,64 L 352,96 L 416,96 L 416,160 L 384,160 L 384,192 ZM 160,96L 224,96L 224,64L 160,64zM 256,96L 320,96L 320,64L 256,64zM 96,160 L 96,96 L 128,96 L 128,64 L 64,64 L 64,192 L 160,192 L 160,160 ZM 480,448 L 32,448 L 32,0 L 480,0 L 480,448 Z M 512,480 L 512,480 L 512-32 L 0-32 L 0,480 L 512,480 Z" />
<glyph unicode="&#xe025;" d="M 224,192 L 128,192 L 128,256 L 224,256 L 224,352 L 288,352 L 288,256 L 384,256 L 384,192 L 288,192 L 288,96 L 224,96 ZM 512,160 L 512-32 L 0-32 L 0,160 L 64,160 L 64,32 L 448,32 L 448,160 Z" />
<glyph unicode="&#xe024;" d="M 64,352l 64,0 l0-96 l 32,0 L 160,448 c0,17.6-14.4,32-32,32L 64,480 C 46.4,480, 32,465.6, 32,448l0-192 l 32,0 L 64,352 z M 64,448l 64,0 l0-64 L 64,384 L 64,448 z M 480,448L 480,480 l-96,0
c-17.601,0-32-14.4-32-32l0-160 c0-17.6, 14.399-32, 32-32l 96,0 l0,32 l-96,0 L 384,448 L 480,448 z M 320,400L 320,448 c0,17.6-14.4,32-32,32l-96,0 l0-224 l 96,0
c 17.6,0, 32,14.4, 32,32l0,48 c0,17.6-4.4,32-22,32C 315.6,368, 320,382.4, 320,400z M 288,288l-64,0 l0,64 l 64,0 L 288,288 z M 288,384l-64,0 L 224,448 l 64,0 L 288,384 zM 416,192 L 208-32 L 96,112 L 137,147 L 208,73 L 384,224 Z" />
<glyph unicode="&#xe023;" d="M 512,480 L 512,288 L 442.87,357.13 L 336.87,251.13 L 283.13,304.87 L 389.13,410.87 L 320,480 ZM 122.87,410.87 L 228.87,304.87 L 175.13,251.13 L 69.13,357.13 L 0,288 L 0,480 L 192,480 ZM 442.87,90.87 L 512,160 L 512-32 L 320-32 L 389.13,37.13 L 283.13,143.13 L 336.87,196.87 ZM 228.87,143.13 L 122.87,37.13 L 192-32 L 0-32 L 0,160 L 69.13,90.87 L 175.13,196.87 Z" />
<glyph unicode="&#xe022;" d="M 128,448L 384,448L 384,384L 128,384zM 480,352L 32,352 C 14.4,352,0,337.6,0,320l0-160 c0-17.6, 14.398-32, 32-32l 96,0 l0-128 l 256,0 L 384,128 l 96,0 c 17.6,0, 32,14.4, 32,32L 512,320
C 512,337.6, 497.6,352, 480,352z M 352,32L 160,32 L 160,192 l 192,0 L 352,32 z M 487.2,304c0-12.813-10.387-23.2-23.199-23.2
c-12.813,0-23.201,10.387-23.201,23.2s 10.388,23.2, 23.201,23.2C 476.814,327.2, 487.2,316.813, 487.2,304z" />
<glyph unicode="&#xe021;" d="M 256,480C 114.615,480,0,365.386,0,224c0-141.385, 114.614-256, 256-256c 141.385,0, 256,114.615, 256,256
C 512,365.386, 397.385,480, 256,480z M 256,8c-119.293,0-216,96.706-216,216c0,119.293, 96.707,216, 216,216c 119.295,0, 216-96.707, 216-216
C 472,104.706, 375.295,8, 256,8z M 192,320c0-17.673-14.327-32-32-32s-32,14.327-32,32s 14.327,32, 32,32S 192,337.673, 192,320z
M 384,320c0-17.673-14.326-32-32-32s-32,14.327-32,32s 14.326,32, 32,32S 384,337.673, 384,320zM 256,154 C 326.537,154 387.344,182.766 415.231,215.596 C 404.795,129.986 337.087,64 256,64 C 174.941,64 107.251,130.013 96.778,215.584 C 124.671,182.761 185.471,154 256,154 Z" />
<glyph unicode="&#xe020;" d="M 352,32 L 480,32 L 512,96 L 512-32 L 320-32 L 320,75.107 C 385.556,103.349 432,173.688 432,256 C 432,363.216 353.201,447.133 256,447.133 C 158.797,447.133 80,363.217 80,256 C 80,173.688 126.443,103.349 192,75.107 L 192-32 L 0-32 L 0,96 L 32,32 L 160,32 L 160,48.295 C 66.185,81.525 0,161.996 0,256 C 0,379.712 114.615,480 256,480 C 397.385,480 512,379.712 512,256 C 512,161.996 445.815,81.525 352,48.295 L 352,32 Z" />
<glyph unicode="&#xe01f;" d="M 384,377 L 384,352 L 448,352 L 448,320 L 352,320 L 352,393 L 416,423 L 416,448 L 352,448 L 352,480 L 448,480 L 448,407 ZM 338,352L 270,352L 176,258L 82,352L 14,352L 142,224L 14,96L 82,96L 176,190L 270,96L 338,96L 210,224 z" />
<glyph unicode="&#xe01e;" d="M 384,25 L 384,0 L 448,0 L 448-32 L 352-32 L 352,41 L 416,71 L 416,96 L 352,96 L 352,128 L 448,128 L 448,55 ZM 338,352L 270,352L 176,258L 82,352L 14,352L 142,224L 14,96L 82,96L 176,190L 270,96L 338,96L 210,224 z" />
<glyph unicode="&#xe01d;" d="M0,32L 288,32L 288-32L0-32zM 96,480L 448,480L 448,416L 96,416zM 138.694,64 L 241.038,456.082 L 302.963,439.918 L 204.838,64 ZM 464.887-32 L 400,32.887 L 335.113-32 L 304-0.887 L 368.887,64 L 304,128.887 L 335.113,160 L 400,95.113 L 464.887,160 L 496,128.887 L 431.113,64 L 496-0.887 Z" />
<glyph unicode="&#xe01c;" d="M0,256L 512,256L 512,192L0,192z" />
<glyph unicode="&#xe01b;" d="M0,448l0-448 l 512,0 L 512,448 L0,448 z M 192,160l0,96 l 128,0 l0-96 L 192,160 z M 320,128l0-96 L 192,32 l0,96 L 320,128 z M 320,384l0-96 L 192,288 L 192,384 L 320,384 z M 160,384l0-96 L 32,288 L 32,384 L 160,384 z
M 32,256l 128,0 l0-96 L 32,160 L 32,256 z M 352,256l 128,0 l0-96 L 352,160 L 352,256 z M 352,288L 352,384 l 128,0 l0-96 L 352,288 z M 32,128l 128,0 l0-96 L 32,32 L 32,128 z M 352,32l0,96 l 128,0 l0-96 L 352,32 z" />
<glyph unicode="&#xe01a;" d="M 161.009,64l 28.8,96l 132.382,0 l 28.8-96l 56.816,0 L 311.809,384L 200.191,384 l-96-320L 161.009,64 z M 237.809,320l 36.382,0 l 28.8-96l-93.982,0
L 237.809,320z" />
<glyph unicode="&#xe019;" d="M 256,320C 151.316,320, 58.378,269.722,0,192c 58.378-77.723, 151.316-128, 256-128c 104.684,0, 197.622,50.277, 256,128
C 453.622,269.722, 360.684,320, 256,320z M 224,256c 17.673,0, 32-14.327, 32-32s-14.327-32-32-32s-32,14.327-32,32S 206.327,256, 224,256z
M 386.808,127.352c-19.824-10.129-40.826-17.931-62.423-23.188C 302.141,98.746, 279.134,96, 256,96
c-23.133,0-46.141,2.746-68.384,8.162c-21.597,5.259-42.599,13.061-62.423,23.188c-31.51,16.101-60.111,38.205-83.82,64.649
c 23.709,26.444, 52.31,48.55, 83.82,64.649c 16.168,8.261, 33.121,14.973, 50.541,20.020C 165.79,261.547, 160,243.451, 160,224
c0-53.020, 42.981-96, 96-96c 53.019,0, 96,42.98, 96,96c0,19.451-5.791,37.547-15.733,52.67c 17.419-5.048, 34.372-11.76, 50.541-20.021
c 31.511-16.099, 60.109-38.204, 83.819-64.649C 446.917,165.557, 418.318,143.45, 386.808,127.352z M 430.459,358.139
C 376.099,385.916, 317.403,400, 256,400c-61.403,0-120.099-14.084-174.459-41.861C 52.155,343.123, 24.675,324.187,0,302.101l0-54.603
c 27.669,29.283, 60.347,53.877, 96.097,72.145C 145.907,345.095, 199.706,358, 256,358s 110.093-12.905, 159.902-38.358
c 35.751-18.268, 68.429-42.862, 96.098-72.145L 512,302.1 C 487.325,324.187, 459.846,343.123, 430.459,358.139z" />
<glyph unicode="&#xe018;" d="M 256,384C 149.962,384, 64,298.039, 64,192s 85.961-192, 192-192c 106.037,0, 192,85.961, 192,192S 362.037,384, 256,384z
M 357.822,90.177C 330.626,62.979, 294.464,48, 256,48s-74.625,14.979-101.823,42.177C 126.979,117.374, 112,153.536, 112,192
s 14.979,74.625, 42.177,101.823C 181.375,321.021, 217.536,336, 256,336s 74.626-14.979, 101.821-42.177
C 385.022,266.625, 400,230.464, 400,192S 385.021,117.374, 357.822,90.177zM 162.965,378.069l-21.47,42.939C 92.058,396.24, 51.76,355.942, 26.992,306.504l 42.938-21.47
C 90.054,325.202, 122.796,357.945, 162.965,378.069zM 442.067,285.035l 42.939,21.469C 460.24,355.942, 419.943,396.24, 370.504,421.008l-21.472-42.939
C 389.201,357.945, 421.944,325.203, 442.067,285.035zM 256,288l-32,0 l0-96 c0-5.055, 2.35-9.555, 6.011-12.486l-0.006-0.008l 80-64l 19.988,24.988L 256,199.689L 256,288 z" />
<glyph unicode="&#xe017;" d="M 160,352L 32,224L 160,96L 224,96L 96,224L 224,352 zM 352,352L 288,352L 416,224L 288,96L 352,96L 480,224 z" />
<glyph unicode="&#xe016;" d="M 224,128L 288,128L 288,64L 224,64zM 352,352 C 369.673,352 384,337.673 384,320 L 384,224 L 288,160 L 224,160 L 224,192 L 320,256 L 320,288 L 160,288 L 160,352 L 352,352 ZM 256,432 C 200.441,432 148.208,410.364 108.922,371.078 C 69.636,331.792 48,279.559 48,224 C 48,168.441 69.636,116.208 108.922,76.922 C 148.208,37.636 200.441,16 256,16 C 311.559,16 363.792,37.636 403.078,76.922 C 442.364,116.208 464,168.441 464,224 C 464,279.559 442.364,331.792 403.078,371.078 C 363.792,410.364 311.559,432 256,432 Z M 256,480 L 256,480 C 397.385,480 512,365.385 512,224 C 512,82.615 397.385-32 256-32 C 114.615-32 0,82.615 0,224 C 0,365.385 114.615,480 256,480 Z" />
<glyph unicode="&#xe015;" d="M0,416l0-384 l 512,0 L 512,416 L0,416 z M 96,64L 32,64 l0,64 l 64,0 L 96,64 z M 96,192L 32,192 l0,64 l 64,0 L 96,192 z M 96,320L 32,320 L 32,384 l 64,0 L 96,320 z M 384,64L 128,64 L 128,384 l 256,0 L 384,64 z
M 480,64l-64,0 l0,64 l 64,0 L 480,64 z M 480,192l-64,0 l0,64 l 64,0 L 480,192 z M 480,320l-64,0 L 416,384 l 64,0 L 480,320 zM 192,320L 192,128L 320,224 z" />
<glyph unicode="&#xe014;" d="M0,416l0-416 l 512,0 L 512,416 L0,416 z M 480,32L 32,32 L 32,384 l 448,0 L 480,32 zM 352,304A48,48 1980 1 0 448,304A48,48 1980 1 0 352,304zM 448,64 L 64,64 L 160,320 L 288,160 L 352,208 Z" />
<glyph unicode="&#xe013;" d="M 96,480l0-512 l 160,160l 160-160L 416,480 L 96,480 z M 384,45.255l-128,128l-128-128L 128,448 l 256,0 L 384,45.255 z" />
<glyph unicode="&#xe012;" d="M 238.444,142.443c 2.28-4.524, 3.495-9.579, 3.495-14.848c0-8.808-3.372-17.029-9.496-23.154l-81.69-81.69
c-6.124-6.124-14.348-9.496-23.154-9.496s-17.030,3.372-23.154,9.496l-49.69,49.69c-6.124,6.125-9.496,14.348-9.496,23.154
s 3.372,17.030, 9.496,23.154l 81.69,81.691c 6.124,6.123, 14.348,9.496, 23.154,9.496c 5.269,0, 10.322-1.215, 14.848-3.494l 32.669,32.668
c-13.935,10.705-30.72,16.080-47.517,16.080c-19.993,0-39.986-7.583-55.154-22.751l-81.69-81.691
c-30.335-30.335-30.335-79.975,0-110.309l 49.69-49.691c 15.167-15.166, 35.16-22.75, 55.153-22.75
c 19.994,0, 39.987,7.584, 55.154,22.751l 81.69,81.69c 27.91,27.91, 30.119,72.149, 6.672,102.673L 238.444,142.443zM 489.248,407.558l-49.69,49.691C 424.391,472.417, 404.398,480, 384.404,480c-19.993,0-39.985-7.583-55.153-22.751l-81.691-81.691
c-27.91-27.91-30.119-72.149-6.671-102.671l 32.669,32.67c-2.279,4.525-3.494,9.58-3.494,14.847c0,8.808, 3.372,17.030, 9.496,23.154
l 81.691,81.691c 6.123,6.124, 14.347,9.497, 23.153,9.497c 8.808,0, 17.030-3.373, 23.154-9.497l 49.69-49.691
c 6.124-6.124, 9.496-14.347, 9.496-23.154c0-8.807-3.372-17.030-9.496-23.154l-81.69-81.691c-6.124-6.124-14.347-9.496-23.154-9.496
c-5.268,0-10.322,1.215-14.848,3.495l-32.669-32.669c 13.936-10.705, 30.72-16.080, 47.517-16.080c 19.994,0, 39.987,7.584, 55.154,22.752
l 81.69,81.69C 519.584,327.584, 519.584,377.223, 489.248,407.558zM 116.684,340.688L 20.687,436.685L 43.315,459.313L 139.312,363.316zM 192,480L 224,480L 224,384L 192,384zM0,288L 96,288L 96,256L0,256zM 395.316,107.312L 491.314,11.314L 468.686-11.314L 372.688,84.684zM 288,64L 320,64L 320-32L 288-32zM 416,192L 512,192L 512,160L 416,160z" />
<glyph unicode="&#xe011;" d="M 160,128c 8.8-8.8, 23.637-8.363, 32.971,0.971L 351.030,287.029C 360.364,296.363, 360.8,311.2, 352,320
s-23.637,8.363-32.971-0.971L 160.971,160.971C 151.637,151.637, 151.2,136.8, 160,128zM 238.444,142.444c 2.28-4.525, 3.495-9.58, 3.495-14.848c0-8.808-3.372-17.030-9.496-23.154l-81.691-81.691
c-6.124-6.124-14.347-9.496-23.154-9.496s-17.030,3.372-23.154,9.496l-49.691,49.691c-6.124,6.124-9.496,14.347-9.496,23.154
s 3.372,17.030, 9.496,23.154l 81.691,81.691c 6.124,6.124, 14.347,9.497, 23.154,9.497c 5.268,0, 10.322-1.215, 14.848-3.495l 32.669,32.669
c-13.935,10.705-30.72,16.080-47.517,16.080c-19.993,0-39.986-7.583-55.154-22.751l-81.691-81.691
c-30.335-30.335-30.335-79.974,0-110.309l 49.691-49.691C 87.611-24.416, 107.604-32, 127.597-32
c 19.994,0, 39.987,7.584, 55.154,22.751l 81.691,81.691c 27.91,27.91, 30.119,72.149, 6.672,102.672L 238.444,142.444zM 489.249,407.558l-49.691,49.691C 424.391,472.417, 404.398,480, 384.404,480c-19.993,0-39.986-7.583-55.154-22.751l-81.691-81.691
c-27.91-27.91-30.119-72.149-6.671-102.671l 32.669,32.67c-2.279,4.525-3.494,9.58-3.494,14.847c0,8.808, 3.372,17.030, 9.496,23.154
l 81.691,81.691c 6.124,6.124, 14.347,9.497, 23.154,9.497s 17.030-3.373, 23.154-9.497l 49.691-49.691
c 6.124-6.124, 9.496-14.347, 9.496-23.154s-3.372-17.030-9.496-23.154l-81.691-81.691c-6.124-6.124-14.347-9.496-23.154-9.496
c-5.268,0-10.322,1.215-14.848,3.495l-32.669-32.669c 13.936-10.705, 30.72-16.080, 47.517-16.080c 19.994,0, 39.987,7.584, 55.154,22.751
l 81.691,81.691C 519.584,327.584, 519.584,377.223, 489.249,407.558z" />
<glyph unicode="&#xe010;" d="M 288,355.814L 288,480 l 192-192L 288,96L 288,222.912 C 64.625,228.153, 74.206,71.016, 131.070-32
C-9.286,119.707, 20.52,362.785, 288,355.814z" />
<glyph unicode="&#xe00f;" d="M 380.931-32C 437.794,71.016, 447.375,228.153, 224,222.912L 224,96 L 32,288L 224,480l0-124.186
C 491.481,362.785, 521.285,119.707, 380.931-32z" />
<glyph unicode="&#xe00e;" d="M 112.5,256 C 174.356,256 224.5,205.855 224.5,144 C 224.5,82.144 174.356,32 112.5,32 C 50.644,32 0.5,82.144 0.5,144 L 0,160 C 0,283.712 100.288,384 224,384 L 224,320 C 181.263,320 141.083,303.357 110.863,273.137 C 105.046,267.319 99.737,261.129 94.948,254.627 C 100.667,255.527 106.528,256 112.5,256 ZM 400.5,256 C 462.355,256 512.5,205.855 512.5,144 C 512.5,82.144 462.355,32 400.5,32 C 338.645,32 288.5,82.144 288.5,144 L 288,160 C 288,283.712 388.288,384 512,384 L 512,320 C 469.263,320 429.083,303.357 398.863,273.137 C 393.045,267.319 387.736,261.129 382.947,254.627 C 388.667,255.527 394.527,256 400.5,256 Z" />
<glyph unicode="&#xe00d;" d="M0,448L 512,448L 512,384L0,384zM 192,352L 512,352L 512,288L 192,288zM 192,256L 512,256L 512,192L 192,192zM 192,160L 512,160L 512,96L 192,96zM0,64L 512,64L 512,0L0,0zM 128,320 L 128,128 L 0,224 Z" />
<glyph unicode="&#xe00c;" d="M0,448L 512,448L 512,384L0,384zM 192,352L 512,352L 512,288L 192,288zM 192,256L 512,256L 512,192L 192,192zM 192,160L 512,160L 512,96L 192,96zM0,64L 512,64L 512,0L0,0zM 0,128 L 0,320 L 128,224 Z" />
<glyph unicode="&#xe00b;" d="M 192,64L 512,64L 512,0L 192,0zM 192,256L 512,256L 512,192L 192,192zM 192,448L 512,448L 512,384L 192,384zM 96,480 L 96,352 L 64,352 L 64,448 L 32,448 L 32,480 ZM 64,217 L 64,192 L 128,192 L 128,160 L 32,160 L 32,233 L 96,263 L 96,288 L 32,288 L 32,320 L 128,320 L 128,247 ZM 128,128 L 128-32 L 32-32 L 32,0 L 96,0 L 96,32 L 32,32 L 32,64 L 96,64 L 96,96 L 32,96 L 32,128 Z" />
<glyph unicode="&#xe00a;" d="M 192,448l 320,0 l0-64 L 192,384 L 192,448 z M 192,256l 320,0 l0-64 L 192,192 L 192,256 z M 192,64l 320,0 l0-64 L 192,0 L 192,64 zM0,416A64,64 1980 1 0 128,416A64,64 1980 1 0 0,416zM0,224A64,64 1980 1 0 128,224A64,64 1980 1 0 0,224zM0,32A64,64 1980 1 0 128,32A64,64 1980 1 0 0,32z" />
<glyph unicode="&#xe009;" d="M 32,480L 224,480L 224,448L 32,448zM 288,480L 480,480L 480,448L 288,448zM 476,320l-28,0 L 448,448 L 320,448 l0-128 L 192,320 L 192,448 L 64,448 l0-128 L 36,320 c-19.8,0-36-16.2-36-36l0-280 c0-19.8, 16.2-36, 36-36l 152,0 c 19.8,0, 36,16.2, 36,36L 224,192 l 64,0
l0-188 c0-19.8, 16.2-36, 36-36l 152,0 c 19.8,0, 36,16.2, 36,36L 512,284 C 512,303.8, 495.8,320, 476,320z M 174,0L 50,0 c-9.9,0-18,7.2-18,16
s 8.1,16, 18,16l 124,0 c 9.9,0, 18-7.2, 18-16S 183.9,0, 174,0z M 272,224l-32,0 c-8.8,0-16,7.2-16,16s 7.2,16, 16,16l 32,0 c 8.8,0, 16-7.2, 16-16
S 280.8,224, 272,224z M 462,0L 338,0 c-9.9,0-18,7.2-18,16s 8.1,16, 18,16l 124,0 c 9.9,0, 18-7.2, 18-16S 471.9,0, 462,0z" />
<glyph unicode="&#xe008;" d="M 416,320L 416,400 c0,8.8-7.2,16-16,16L 288,416 L 288,448 c0,17.6-14.4,32-32,32l-64,0 c-17.602,0-32-14.4-32-32l0-32 L 48,416 c-8.801,0-16-7.2-16-16l0-320
c0-8.8, 7.199-16, 16-16l 144,0 l0-96 l 224,0 l 96,96L 512,320 L 416,320 z M 192,447.943c 0.017,0.019, 0.036,0.039, 0.057,0.057l 63.884,0
c 0.021-0.018, 0.041-0.038, 0.059-0.057L 256,416 l-64,0 L 192,447.943 z M 96,352L 96,384 l 256,0 l0-32 L 96,352 z M 416,13.255L 416,64 l 50.745,0 L 416,13.255z M 480,96l-96,0 l0-96
L 224,0 L 224,288 l 256,0 L 480,96 z" />
<glyph unicode="&#xe007;" d="M 445.387,125.423c-22.827,22.778-51.864,34.536-78.973,34.536l-14.556,0 l-31.952,32.004l 127.81,128.019
c 31.952,32.005, 31.952,96.014,0,128.019L 256.001,255.973L 64.285,448c-31.952-32.004-31.952-96.014,0-128.019l 127.811-128.017
l-31.953-32.004l-14.557,0 c-27.11,0-56.146-11.759-78.974-34.538c-40.811-40.721-46.325-101.242-12.315-135.175
C 69.282-24.704, 89.441-32, 110.795-32c 27.108,0, 56.145,11.757, 78.973,34.536c 26.792,26.732, 38.371,62, 33.542,92.674l 32.692,32.744
l 32.688-32.744c-4.828-30.674, 6.753-65.941, 33.542-92.674C 345.063-20.243, 374.098-32, 401.206-32
c 21.354,0, 41.512,7.296, 56.497,22.248C 491.713,24.181, 486.197,84.702, 445.387,125.423z M 176.512,57.231
c-3.849-8.941-9.505-17.173-16.813-24.463c-7.318-7.302-15.586-12.959-24.574-16.812c-8.066-3.458-16.48-5.284-24.331-5.284
c-7.573,0-18.306,1.701-26.431,9.806c-8.068,8.052-9.76,18.659-9.76,26.144c0,7.771, 1.821,16.105, 5.263,24.106
c 3.85,8.942, 9.507,17.173, 16.813,24.463c 7.317,7.303, 15.586,12.957, 24.575,16.812c 8.067,3.457, 16.48,5.284, 24.332,5.284
c 7.573,0, 18.306-1.7, 26.429-9.807c 8.067-8.049, 9.761-18.658, 9.761-26.142C 181.777,73.567, 179.957,65.23, 176.512,57.231z
M 256.002,146.702c-24.957,0-45.188,20.266-45.188,45.263c0,24.996, 20.231,45.26, 45.188,45.26s 45.186-20.264, 45.186-45.26
C 301.188,166.966, 280.958,146.702, 256.002,146.702z M 427.636,20.479c-8.124-8.104-18.856-9.806-26.43-9.806
c-7.852,0-16.265,1.826-24.333,5.284c-8.986,3.853-17.254,9.51-24.571,16.812c-7.307,7.29-12.963,15.521-16.813,24.463
c-3.443,7.999-5.263,16.336-5.263,24.106c0,7.483, 1.692,18.094, 9.76,26.143c 8.123,8.104, 18.856,9.807, 26.43,9.807
c 7.85,0, 16.265-1.827, 24.33-5.284c 8.989-3.854, 17.258-9.509, 24.575-16.812c 7.305-7.29, 12.962-15.521, 16.813-24.463
c 3.442-7.999, 5.263-16.335, 5.263-24.106C 437.396,39.138, 435.702,28.53, 427.636,20.479z" />
<glyph unicode="&#xe006;" d="M0,448L 512,448L 512,384L0,384zM0,352L 512,352L 512,288L0,288zM0,256L 512,256L 512,192L0,192zM0,160L 512,160L 512,96L0,96zM0,64L 512,64L 512,0L0,0z" />
<glyph unicode="&#xe005;" d="M0,448L 512,448L 512,384L0,384zM 192,352L 512,352L 512,288L 192,288zM 192,160L 512,160L 512,96L 192,96zM0,256L 512,256L 512,192L0,192zM0,64L 512,64L 512,0L0,0z" />
<glyph unicode="&#xe004;" d="M0,448L 512,448L 512,384L0,384zM 96,352L 416,352L 416,288L 96,288zM 96,160L 416,160L 416,96L 96,96zM0,256L 512,256L 512,192L0,192zM0,64L 512,64L 512,0L0,0z" />
<glyph unicode="&#xe003;" d="M0,448L 512,448L 512,384L0,384zM0,352L 320,352L 320,288L0,288zM0,160L 320,160L 320,96L0,96zM0,256L 512,256L 512,192L0,192zM0,64L 512,64L 512,0L0,0z" />
<glyph unicode="&#xe002;" d="M 512,183.771l0,80.458 l-79.572,7.957c-4.093,15.021-10.044,29.274-17.605,42.49l 52.298,63.919L 410.595,435.12l-63.918-52.298
c-13.217,7.562-27.471,13.513-42.491,17.604L 296.229,480l-80.458,0 l-7.957-79.573c-15.021-4.093-29.274-10.043-42.49-17.604
L 101.405,435.12L 44.88,378.595l 52.298-63.918c-7.562-13.216-13.513-27.47-17.605-42.49L0,264.229l0-80.458 l 79.573-7.957
c 4.093-15.021, 10.043-29.274, 17.605-42.491L 44.88,69.405l 56.524-56.524l 63.919,52.298c 13.216-7.562, 27.47-13.514, 42.49-17.605
L 215.771-32l 80.458,0 l 7.957,79.572c 15.021,4.093, 29.274,10.044, 42.491,17.605l 63.918-52.298l 56.524,56.524l-52.298,63.918
c 7.562,13.217, 13.514,27.471, 17.605,42.49L 512,183.771z M 352,192l-64-64l-64,0 l-64,64l0,64 l 64,64l 64,0 l 64-64L 352,192 z" />
<glyph unicode="&#xe001;" d="M 451.716,380.285l-71.432,71.431C 364.728,467.272, 334,480, 312,480L 72,480 C 50,480, 32,462, 32,440l0-432 c0-22, 18-40, 40-40l 368,0 c 22,0, 40,18, 40,40
L 480,312 C 480,334, 467.272,364.729, 451.716,380.285z M 429.089,357.657c 1.565-1.565, 3.125-3.487, 4.64-5.657L 352,352 L 352,433.728
c 2.17-1.515, 4.092-3.075, 5.657-4.64L 429.089,357.657z M 448,8c0-4.336-3.664-8-8-8L 72,0 c-4.336,0-8,3.664-8,8L 64,440 c0,4.336, 3.664,8, 8,8
l 240,0 c 2.416,0, 5.127-0.305, 8-0.852L 320,320 l 127.148,0 c 0.547-2.873, 0.852-5.583, 0.852-8L 448,8 z" />
<glyph unicode="&#xe000;" d="M 448,480L0,480 l0-512 l 512,0 L 512,416 L 448,480z M 256,416l 64,0 l0-128 l-64,0 L 256,416 z M 448,32L 64,32 L 64,416 l 32,0 l0-160 l 288,0 L 384,416 l 37.489,0 L 448,389.491L 448,32 z" />
<glyph unicode="&#xe033;" d="M 64,208L 208,64L 448,304L 384,368L 208,192L 128,272 z" />
<glyph unicode="&#xe035;" d="M 256,224L 256,160L 272,160L 288,192L 320,192L 320,64L 296,64L 296,32L 408,32L 408,64L 384,64L 384,192L 416,192L 432,160L 448,160L 448,224 zM 416,320L 416,400 c0,8.8-7.2,16-16,16L 288,416 L 288,448 c0,17.6-14.4,32-32,32l-64,0 c-17.602,0-32-14.4-32-32l0-32 L 48,416 c-8.801,0-16-7.2-16-16l0-320
c0-8.8, 7.199-16, 16-16l 144,0 l0-96 l 320,0 L 512,320 L 416,320 z M 192,447.943c 0.017,0.019, 0.036,0.039, 0.057,0.057l 63.884,0
c 0.021-0.018, 0.041-0.038, 0.059-0.057L 256,416 l-64,0 L 192,447.943 z M 96,352L 96,384 l 256,0 l0-32 L 96,352 z M 480,0L 224,0 L 224,288 l 256,0 L 480,0 z" />
<glyph unicode="&#x20;" horiz-adv-x="256" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 B

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More