{{ shown_user }}
+
+ {% if shown_user.committee %}
+
{{ shown_user.committee }}
+ {% endif %}
+
+ {% if shown_user.groups.all %}
+ {% for group in shown_user.groups.all %}
+ {% trans group.name %}{% if not forloop.last %}, {% endif %}
+ {% endfor %}
+ {% endif %}
+
{{ shown_user }}
-
- {% if shown_user.committee %}
-
{{ shown_user.committee }}
- {% endif %}
-
- {% if shown_user.groups.all %}
- {% for group in shown_user.groups.all %}
- {% trans group.name %}{% if not forloop.last %}, {% endif %}
- {% endfor %}
- {% endif %}
-
-
-
-{% endblock %}
diff --git a/openslides/participant/views.py b/openslides/participant/views.py
index f1151dc2e..2d0b04801 100644
--- a/openslides/participant/views.py
+++ b/openslides/participant/views.py
@@ -43,11 +43,12 @@ from openslides.utils.views import (
RedirectView, SingleObjectMixin, ListView, QuestionMixin, DetailView)
from openslides.config.api import config
from openslides.projector.projector import Widget
-from openslides.participant.api import gen_username, gen_password, import_users
-from openslides.participant.forms import (
+
+from .api import gen_username, gen_password, import_users
+from .forms import (
UserCreateForm, UserUpdateForm, UsersettingsForm,
UserImportForm, GroupForm)
-from openslides.participant.models import User, Group, get_protected_perm
+from .models import User, Group, get_protected_perm
class UserOverview(ListView):
diff --git a/openslides/projector/__init__.py b/openslides/projector/__init__.py
index 39748e2c6..47bd8c0e5 100644
--- a/openslides/projector/__init__.py
+++ b/openslides/projector/__init__.py
@@ -10,4 +10,4 @@
:license: GNU GPL, see LICENSE for more details.
"""
-from . import signals
+from . import signals, slides
diff --git a/openslides/projector/api.py b/openslides/projector/api.py
index 68299d82b..a0937a54f 100644
--- a/openslides/projector/api.py
+++ b/openslides/projector/api.py
@@ -10,114 +10,146 @@
:license: GNU GPL, see LICENSE for more details.
"""
+import json
+
from django.conf import settings
from django.core.cache import cache
from django.utils.datastructures import SortedDict
from django.utils.importlib import import_module
+from django.template.loader import render_to_string
from openslides.config.api import config
-from openslides.projector.projector import SLIDE, Slide
+from openslides.utils.tornado_webserver import ProjectorSocketHandler
+from .signals import projector_overlays
-def split_sid(sid):
+slide_callback = {}
+"""
+A dictonary where the key is the name of a slide, and the value is a
+callable object which returns the html code for a slide.
+"""
+
+
+def update_projector():
"""
- Slit a SID in the model-part and in the model-id
+ Sends the data to the clients, who listen to the projector.
"""
+ # TODO: only send necessary html
+ ProjectorSocketHandler.send_updates({'content': get_projector_content()})
+
+
+def update_projector_overlay(overlay):
+ """
+ Update one overlay on the projector.
+
+ Checks if the overlay is activated and updates it in this case.
+
+ 'overlay' has to be an overlay object, the name of a ovleray or None.
+
+ If 'overlay' is None, then all overlays are updated.
+ """
+ if isinstance(overlay, basestring):
+ overlay = get_overlays()[overlay]
+ if overlay is None:
+ overlays = [overlay for overlay in get_overlays().values()]
+ else:
+ overlays = [overlay]
+
+ overlay_dict = {}
+ for overlay in overlays:
+ if overlay.is_active():
+ overlay_dict[overlay.name] = {
+ 'html': overlay.get_projector_html(),
+ 'javascript': overlay.get_javascript()}
+ else:
+ overlay_dict[overlay.name] = None
+ ProjectorSocketHandler.send_updates({'overlays': overlay_dict})
+
+
+def get_projector_content(slide_dict=None):
+ """
+ Returns the HTML-Content block of the projector.
+ """
+ if slide_dict is None:
+ slide_dict = config['projector_active_slide'].copy()
+ callback = slide_dict.pop('callback', None)
+
try:
- data = sid.split('-')
- except AttributeError:
- return None
- if len(data) == 2:
- model = data[0]
- id = data[1]
- return (model, id)
- if len(data) == 1:
- try:
- return (SLIDE[data[0]].key, None)
- except KeyError:
- return None
- return None
-
-
-def get_slide_from_sid(sid, element=False):
- """
- Return the Slide for an given sid.
- If element== False, return the slide-dict,
- else, return the object.
- """
- try:
- key, id = split_sid(sid)
- except TypeError:
- return None
-
- if id is not None:
- try:
- object = SLIDE[key].model.objects.get(pk=id)
- except SLIDE[key].model.DoesNotExist:
- return None
- if element:
- return object
- return object.slide()
- try:
- return SLIDE[key].func()
+ return slide_callback[callback](**slide_dict)
except KeyError:
- return None
+ return default_slide()
-def get_active_slide(only_sid=False):
+def default_slide():
"""
- Returns the active slide. If no slide is active, or it can not find an Item,
- return None
-
- if only_sid is True, returns only the id of this item. Returns None if not
- Item is active.
+ Returns the HTML Code for the default slide.
"""
- sid = config["presentation"]
-
- if only_sid:
- return sid
- return get_slide_from_sid(sid)
+ return render_to_string('projector/default_slide.html')
-def set_active_slide(sid, argument=None):
+def get_overlays():
+ """
+ Returns all overlay objects.
+
+ The returned value is a dictonary with the name of the overlay as key, and
+ the overlay object as value.
+ """
+ overlays = {}
+ for receiver, overlay in projector_overlays.send(sender='get_overlays'):
+ overlays[overlay.name] = overlay
+ return overlays
+
+
+def get_projector_overlays():
+ """
+ Returns the HTML code for all active overlays.
+ """
+ overlays = [{'name': key, 'html': overlay.get_projector_html()}
+ for key, overlay in get_overlays().items()
+ if overlay.is_active()]
+ return render_to_string('projector/all_overlays.html', {'overlays': overlays})
+
+
+def get_projector_overlays_js():
+ """
+ Returns JS-Code for the overlays.
+
+ The retuned value is a list of json objects.
+ """
+ js = []
+ for key, overlay in get_overlays().items():
+ if overlay.is_active():
+ overlay_js = overlay.get_javascript()
+ if overlay_js:
+ js.append(json.dumps(overlay_js))
+ return js
+
+
+def register_slide(name, callback):
+ """
+ Register a function as slide callback.
+ """
+ slide_callback[name] = callback
+
+
+def set_active_slide(callback, kwargs={}):
"""
Set the active Slide.
+
+ callback: The name of the slide callback.
+ kwargs: Keyword arguments for the slide callback.
"""
- config["presentation"] = sid
- config['presentation_argument'] = argument
- clear_projector_cache()
+ kwargs.update(callback=callback)
+ config['projector_active_slide'] = kwargs
+ update_projector()
+ update_projector_overlay(None)
-def clear_projector_cache():
- cache.delete('projector_content')
- cache.delete('projector_scrollcontent')
- cache.delete('projector_data')
-
-
-def register_slidemodel(model, model_name=None, control_template=None, weight=0):
+def get_active_slide():
"""
- Register a Model as a slide.
+ Returns the dictonary, witch defindes the active slide.
"""
- # TODO: control_template should never be None
- if model_name is None:
- model_name = model.prefix
-
- category = model.__module__.split('.')[0]
- SLIDE[model_name] = Slide(model_slide=True, model=model, category=category,
- key=model.prefix, model_name=model_name,
- control_template=control_template, weight=weight)
-
-
-def register_slidefunc(key, func, control_template=None, weight=0, name=''):
- """
- Register a function for as a slide.
- """
- if control_template is None:
- control_template = 'projector/default_control_slidefunc.html'
- category = func.__module__.split('.')[0]
- SLIDE[key] = Slide(model_slide=False, func=func, category=category,
- key=key, control_template=control_template, weight=weight,
- name=name,)
+ return config['projector_active_slide']
def get_all_widgets(request, session=False):
@@ -135,9 +167,11 @@ def get_all_widgets(request, session=False):
except ImportError:
continue
try:
- module_widgets = mod.get_widgets(request)
+ mod_get_widgets = mod.get_widgets
except AttributeError:
continue
+ else:
+ module_widgets = mod_get_widgets(request)
all_module_widgets.extend(module_widgets)
all_module_widgets.sort(key=lambda widget: widget.default_weight)
session_widgets = request.session.get('widgets', {})
diff --git a/openslides/projector/models.py b/openslides/projector/models.py
index 2dfcd538d..57d2a110f 100644
--- a/openslides/projector/models.py
+++ b/openslides/projector/models.py
@@ -13,34 +13,92 @@
from django.db import models
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy, ugettext_noop
+from django.core.exceptions import ImproperlyConfigured
+from django.core.urlresolvers import reverse
-from openslides.projector.api import register_slidemodel
-from openslides.projector.projector import SlideMixin
+from openslides.utils.utils import int_or_none
-class ProjectorSlide(models.Model, SlideMixin):
+class SlideMixin(object):
+ """
+ A Mixin for a Django-Model, for making the model a slide.
+ """
+
+ slide_callback_name = None
+ """
+ Name of the callback to render the model as slide.
+ """
+
+ def save(self, *args, **kwargs):
+ """
+ Updates the projector, if 'self' is the active slide.
+ """
+ from openslides.projector.api import update_projector
+ super(SlideMixin, self).save(*args, **kwargs)
+ if self.is_active_slide():
+ update_projector()
+
+ def delete(self, *args, **kwargs):
+ from openslides.projector.api import update_projector
+ super(SlideMixin, self).delete(*args, **kwargs)
+ if self.is_active_slide():
+ update_projector()
+
+ def get_slide_callback_name(self):
+ """
+ Returns the name of the slide callback, which is used to render the slide.
+ """
+ if self.slide_callback_name is None:
+ raise ImproperlyConfigured(
+ "SlideMixin requires either a definition of 'slide_callback_name'"
+ " or an implementation of 'get_slide_callback_name()'")
+ else:
+ return self.slide_callback_name
+
+ def get_absolute_url(self, link='projector'):
+ """
+ Return the url to activate the slide, if link == 'projector'
+ """
+ if link == 'projector':
+ url_name = 'projector_activate_slide'
+ elif link == 'projector_preview':
+ url_name = 'projector_preview'
+
+ if link in ('projector', 'projector_preview'):
+ return '%s?pk=%d' % (
+ reverse(url_name,
+ args=[self.get_slide_callback_name()]),
+ self.pk)
+ return super(SlideMixin, self).get_absolute_url(link)
+
+ def is_active_slide(self):
+ """
+ Return True, if the the slide is the active slide.
+ """
+ from openslides.projector.api import get_active_slide
+ active_slide = get_active_slide()
+ pk = int_or_none(active_slide.get('pk', None))
+
+ return (active_slide['callback'] == self.get_slide_callback_name() and
+ self.pk == pk)
+
+
+class ProjectorSlide(SlideMixin, models.Model):
"""
Model for Slides, only for the projector. Also called custom slides.
"""
- prefix = 'ProjectorSlide'
+ slide_callback_name = 'projector_slide'
title = models.CharField(max_length=256, verbose_name=ugettext_lazy("Title"))
text = models.TextField(null=True, blank=True, verbose_name=ugettext_lazy("Text"))
weight = models.IntegerField(default=0, verbose_name=ugettext_lazy("Weight"))
- def slide(self):
- return {
- 'slide': self,
- 'title': self.title,
- 'template': 'projector/ProjectorSlide.html',
- }
-
- @models.permalink
- def get_absolute_url(self, link='edit'):
- if link == 'edit':
- return ('customslide_edit', [str(self.id)])
+ def get_absolute_url(self, link='update'):
+ if link == 'edit' or link == 'update':
+ return reverse('customslide_edit', args=[str(self.pk)])
if link == 'delete':
- return ('customslide_delete', [str(self.id)])
+ return reverse('customslide_delete', args=[str(self.pk)])
+ return super(ProjectorSlide, self).get_absolute_url(link)
def __unicode__(self):
return self.title
@@ -51,6 +109,3 @@ class ProjectorSlide(models.Model, SlideMixin):
('can_see_projector', ugettext_noop("Can see the projector")),
('can_see_dashboard', ugettext_noop("Can see the dashboard")),
)
-
-
-register_slidemodel(ProjectorSlide, control_template='projector/control_customslide.html')
diff --git a/openslides/projector/projector.py b/openslides/projector/projector.py
index d87d74cf0..ede8e3f7e 100644
--- a/openslides/projector/projector.py
+++ b/openslides/projector/projector.py
@@ -20,97 +20,6 @@ from django.template import RequestContext
from openslides.utils.exceptions import OpenSlidesError
-SLIDE = {}
-
-
-class SlideMixin(object):
- """
- A Mixin for a Django-Model, for making the model a slide.
- """
-
- def slide(self):
- """
- Return a map with all Data for the Slide.
- """
- return {
- 'slide': self,
- 'title': 'dummy-title',
- 'template': 'projector/default.html',
- }
-
- @property
- def sid(self):
- """
- Return the sid from this Slide
- """
- return "%s-%d" % (self.prefix, self.id)
-
- @property
- def active(self):
- """
- Return True, if the the slide is the active slide.
- """
- if self.id is None:
- return False
- from openslides.projector.api import get_active_slide
- return get_active_slide(only_sid=True) == self.sid
-
- def set_active(self):
- """
- Appoint this item as the active slide.
- """
- from openslides.projector.api import set_active_slide
- set_active_slide(self.sid)
-
- def save(self, *args, **kwargs):
- if self.active:
- from api import clear_projector_cache
- clear_projector_cache()
- return super(SlideMixin, self).save(*args, **kwargs)
-
-
-class Slide(object):
- """
- Represents a Slide for the projector. Can be a modelinstanz, or a function.
- """
- def __init__(self, model_slide=False, func=None, model=None, category=None,
- key=None, model_name='', control_template='', weight=0, name=''):
- """
- model_slide: Boolean if the value is a Model.
- func: The function to call. Only if modelslide is False.
- model: The model. Only if modelslide is True.
- model_name: The name shown for the model.
- category: The category to show this Slide.
- key: the key in the slide object to find itself.
- """
- self.model_slide = model_slide
- self.func = func
- self.model = model
- self.model_name = model_name
- self.category = category
- self.key = key
- self.control_template = control_template
- self.weight = weight
- self.name = name
-
- @property
- def active(self):
- """
- Return True if the Slide is active, else: False.
- """
- from api import get_active_slide
- return get_active_slide(True) == self.key
-
- def get_items(self):
- """
- If the Slide is a Slide from a Model, return all Objects.
- """
- try:
- return self.model.objects.all()
- except AttributeError:
- return 'No Model'
-
-
class Widget(object):
"""
Class for a Widget for the Projector-Tab.
@@ -158,23 +67,52 @@ class Overlay(object):
Represents an overlay which can be seen on the projector.
"""
- def __init__(self, name, get_widget_html, get_projector_html):
+ def __init__(self, name, get_widget_html, get_projector_html,
+ get_javascript=None, allways_active=False):
self.name = name
self.widget_html_callback = get_widget_html
self.projector_html_callback = get_projector_html
+ self.javascript_callback = get_javascript
+ self.allways_active = allways_active
def get_widget_html(self):
- return self.widget_html_callback()
+ value = None
+ if self.widget_html_callback is not None:
+ value = self.widget_html_callback()
+ return value
def get_projector_html(self):
- try:
- return self._projector_html
- except AttributeError:
- self._projector_html = self.projector_html_callback()
- return self.get_projector_html()
+ return self.get_html_wrapper(self.projector_html_callback())
+
+ def get_javascript(self):
+ if self.javascript_callback is None:
+ value = {}
+ else:
+ value = self.javascript_callback()
+ return value
+
+ def get_html_wrapper(self, inner_html):
+ full_html = ''
+ if inner_html is not None:
+ full_html = '
%s
' % (self.name, inner_html)
+ return full_html
def is_active(self):
- return self.name in config['projector_active_overlays']
+ return self.allways_active or self.name in config['projector_active_overlays']
+
+ def set_active(self, active):
+ """
+ Publish or depublish the ovleray on the projector.
+
+ publish, if active is true,
+ depublish, if active is false.
+ """
+ active_overlays = set(config['projector_active_overlays'])
+ if active:
+ active_overlays.add(self.name)
+ else:
+ active_overlays.discard(self.name)
+ config['projector_active_overlays'] = list(active_overlays)
def show_on_projector(self):
return self.is_active() and self.get_projector_html() is not None
diff --git a/openslides/projector/signals.py b/openslides/projector/signals.py
index b1700a732..f93c17975 100644
--- a/openslides/projector/signals.py
+++ b/openslides/projector/signals.py
@@ -15,13 +15,12 @@ from django.dispatch import Signal, receiver
from django import forms
from django.template.loader import render_to_string
from django.core.context_processors import csrf
+from django.contrib.staticfiles.templatetags.staticfiles import static
-from openslides.config.api import config
+from openslides.config.api import config, ConfigVariable, ConfigPage
from openslides.config.signals import config_signal
-from openslides.config.api import ConfigVariable, ConfigPage
from .projector import Overlay
-from .api import clear_projector_cache
projector_overlays = Signal(providing_args=['request'])
@@ -34,13 +33,13 @@ def setup_projector_config_variables(sender, **kwargs):
config page.
"""
- presentation = ConfigVariable(
- name='presentation',
- default_value='')
-
- presentation_argument = ConfigVariable(
- name='presentation_argument',
- default_value=None)
+ projector = ConfigVariable(
+ name='projector_active_slide',
+ default_value={'callback': None})
+ """
+ The active slide. The config-value is a dictonary with at least the entrie
+ 'callback'.
+ """
projector_message = ConfigVariable(
name='projector_message',
@@ -76,7 +75,7 @@ def setup_projector_config_variables(sender, **kwargs):
return ConfigPage(
title='No title here', url='bar', required_permission=None, variables=(
- presentation, presentation_argument, projector_message,
+ projector, projector_message,
countdown_time, countdown_start_stamp, countdown_pause_stamp,
countdown_state, bigger, up, projector_active_overlays))
@@ -97,30 +96,32 @@ def countdown(sender, **kwargs):
'countdown_time': config['countdown_time'],
'countdown_state': config['countdown_state']}
context.update(csrf(request))
- return render_to_string('projector/overlay_countdown_widget.html', context)
+ return render_to_string('projector/overlay_countdown_widget.html',
+ context)
+
+ def get_projector_js():
+ """
+ Returns JavaScript for the projector
+ """
+ start = int(config['countdown_start_stamp'])
+ duration = int(config['countdown_time'])
+ pause = int(config['countdown_pause_stamp'])
+ state = config['countdown_state']
+
+ return {
+ 'load_file': static('javascript/countdown.js'),
+ 'projector_countdown_start': start,
+ 'projector_countdown_duration': duration,
+ 'projector_countdown_pause': pause,
+ 'projector_countdown_state': state}
def get_projector_html():
"""
Returns an html-code to show on the projector.
"""
- start = config['countdown_start_stamp']
- duration = config['countdown_time']
- pause = config['countdown_pause_stamp']
- if config['countdown_state'] == 'active':
- seconds = max(0, int(start + duration - time()))
- elif config['countdown_state'] == 'paused':
- seconds = max(0, int(start + duration - pause))
- elif config['countdown_state'] == 'inactive':
- seconds = max(0, int(duration))
- else:
- seconds = 0
- if seconds == 0:
- config['countdown_state'] = 'expired'
- clear_projector_cache()
- return render_to_string('projector/overlay_countdown_projector.html',
- {'seconds': '%02d:%02d' % (seconds / 60, seconds % 60)})
+ return render_to_string('projector/overlay_countdown_projector.html')
- return Overlay(name, get_widget_html, get_projector_html)
+ return Overlay(name, get_widget_html, get_projector_html, get_projector_js)
@receiver(projector_overlays, dispatch_uid="projector_message")
@@ -148,3 +149,26 @@ def projector_message(sender, **kwargs):
return None
return Overlay(name, get_widget_html, get_projector_html)
+
+
+@receiver(projector_overlays, dispatch_uid="projector_clock")
+def projector_clock(sender, **kwargs):
+ """
+ Receiver to show the clock on the projector.
+ """
+ name = 'projector_clock'
+
+ def get_projector_html():
+ """
+ Returns the html-code for the clock.
+ """
+ return render_to_string('projector/overlay_clock_projector.html')
+
+ def get_projector_js():
+ """
+ Returns JavaScript for the projector
+ """
+ return {'load_file': static('javascript/clock.js')}
+
+ return Overlay(name, None, get_projector_html, get_projector_js,
+ allways_active=True)
diff --git a/openslides/projector/slides.py b/openslides/projector/slides.py
new file mode 100644
index 000000000..6ecd7901e
--- /dev/null
+++ b/openslides/projector/slides.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+ openslides.projector.slides
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Slides for the projector app.
+
+ :copyright: 2011–2013 by OpenSlides team, see AUTHORS.
+ :license: GNU GPL, see LICENSE for more details.
+"""
+
+from django.template.loader import render_to_string
+
+from openslides.config.api import config
+from openslides.projector.api import register_slide
+
+from .models import ProjectorSlide
+
+
+def projector_slide(**kwargs):
+ """
+ Return the html code for a custom slide.
+ """
+ slide_pk = kwargs.get('pk', None)
+
+ try:
+ slide = ProjectorSlide.objects.get(pk=slide_pk)
+ except ProjectorSlide.DoesNotExist:
+ slide = None
+
+ context = {'slide': slide}
+ return render_to_string('projector/slide_projectorslide.html', context)
+
+
+register_slide('projector_slide', projector_slide)
diff --git a/openslides/projector/static/javascript/clock.js b/openslides/projector/static/javascript/clock.js
new file mode 100644
index 000000000..6b3de95c4
--- /dev/null
+++ b/openslides/projector/static/javascript/clock.js
@@ -0,0 +1,8 @@
+function update_clock() {
+ var currentTime = new Date();
+ var currentHours = currentTime.getHours();
+ var currentMinutes = currentTime.getMinutes();
+ $('#currentTime').html(currentHours + ':' + currentMinutes);
+ setTimeout('update_clock()', 200);
+}
+update_clock();
diff --git a/openslides/projector/static/javascript/countdown.js b/openslides/projector/static/javascript/countdown.js
new file mode 100644
index 000000000..fb428c948
--- /dev/null
+++ b/openslides/projector/static/javascript/countdown.js
@@ -0,0 +1,25 @@
+function update_countdown() {
+ var time = new Date().getTime() / 1000;
+ var seconds;
+ var start = projector.projector_countdown_start;
+ var duration = projector.projector_countdown_duration;
+ var pause = projector.projector_countdown_pause;
+
+ switch (projector.projector_countdown_state) {
+ case 'active':
+ seconds = start + duration - time;
+ break;
+ case 'paused':
+ seconds = start + duration - pause;
+ break;
+ case 'inactive':
+ seconds = duration;
+ break;
+ }
+ if (seconds !== undefined) {
+ seconds = Math.max(0, Math.floor(seconds));
+ $('#overlay_countdown_inner').html(seconds);
+ }
+ setTimeout('update_countdown()', 200);
+}
+update_countdown();
diff --git a/openslides/projector/static/javascript/projector.js b/openslides/projector/static/javascript/projector.js
index 36d27ee0b..09ad3920d 100644
--- a/openslides/projector/static/javascript/projector.js
+++ b/openslides/projector/static/javascript/projector.js
@@ -1,62 +1,67 @@
/**
* OpenSlides projector functions
*
- * :copyright: 2011, 2012 by OpenSlides team, see AUTHORS.
+ * :copyright: 2011–2013 by OpenSlides team, see AUTHORS.
* :license: GNU GPL, see LICENSE for more details.
*/
-content_hash = null;
+$(document).ready(function() {
+ if ($('#content.reload').length > 0) {
+ updater.start();
+ }
+});
-function presentation_reload() {
- if ($('#config > #ajax').html() == 'on') {
- $.ajax({
- type: 'GET',
- url: '/projector/',
- dataType: 'json',
- success: function(data) {
- $('#currentTime').removeClass('ajax_error');
- var new_content_hash = data['content_hash'];
- if (new_content_hash != content_hash) {
- $('#content').html(data.content);
- content_hash = new_content_hash;
+var projector = {
+ _loaded_files: {},
+
+ load_file: function(src) {
+ if (projector._loaded_files[src] === undefined) {
+ projector._loaded_files[src] = document.createElement('script');
+ projector._loaded_files[src].setAttribute("type","text/javascript");
+ projector._loaded_files[src].setAttribute("src", src);
+ $('head').append(projector._loaded_files[src]);
+ }
+ },
+
+ update_data: function(data) {
+ $.each(data, function (key, value) {
+ if (key === 'load_file')
+ projector.load_file(value);
+ else
+ projector[key] = value;
+ });
+ }
+};
+
+var updater = {
+ socket: null,
+
+ start: function() {
+ var url = "ws://" + location.host + "/projector/socket/";
+ updater.socket = new WebSocket(url);
+ updater.socket.onmessage = function(event) {
+ updater.updateProjector(JSON.parse(event.data));
+ }
+ updater.socket.onclose = function() {
+ setTimeout('updater.start()', 5000);
+ }
+ },
+
+ updateProjector: function(data) {
+ $('#content').html(data.content);
+ var overlays = data.overlays;
+ $.each(overlays, function (key, value) {
+ var overlay = $('#overlays #overlay_' + key)
+ if (!value)
+ overlay.remove();
+ else {
+ if (overlay.length) {
+ overlay.html(value.html)
+ } else {
+ $('#overlays').append(value.html);
}
- $('#scrollcontent').html(data.scrollcontent);
- document.title = data.title;
- $('#currentTime').html(data.time);
- $('#content').clearQueue();
- // content font-size
- $('#content').animate({'font-size': data.bigger + '%'}, 200);
- $('#content #sidebar').css({'font-size': '18px'}, 0);
- $('#scrollcontent').animate({'font-size': data.bigger + '%'}, 100);
- // content position
- $('#scrollcontent').animate({'margin-top': data.up + 'em'}, 100);
- // overlays
- $('#overlays div').remove();
- $.each(data['overlays'], function (index, overlay){
- $('#overlays').append('