Mostly Javascript refactoring.
authorŁukasz Rekucki <lrekucki@gmail.com>
Fri, 26 Mar 2010 22:56:41 +0000 (23:56 +0100)
committerŁukasz Rekucki <lrekucki@gmail.com>
Fri, 26 Mar 2010 22:56:41 +0000 (23:56 +0100)
18 files changed:
apps/wiki/templates/wiki/document_details.html
apps/wiki/templates/wiki/history_panel.html [new file with mode: 0644]
apps/wiki/urls.py
apps/wiki/views.py
lib/vstorage.py
lib/wlapi.py [new file with mode: 0644]
platforma/settings.py
platforma/static/css/history.css [new file with mode: 0644]
platforma/static/css/master.css
platforma/static/js/main.js [deleted file]
platforma/static/js/wiki/base.js [new file with mode: 0644]
platforma/static/js/wiki/history.js [new file with mode: 0644]
platforma/static/js/wiki/main.js [new file with mode: 0644]
platforma/static/js/wiki/source_editor.js [new file with mode: 0644]
platforma/static/js/wiki/wikiapi.js [new file with mode: 0644]
platforma/static/js/wiki/wysiwyg_editor.js [new file with mode: 0644]
platforma/static/js/wiki/xslt.js [new file with mode: 0644]
platforma/static/js/xslt.js [deleted file]

index c54ff15..75cf617 100644 (file)
 {% extends "base.html" %}
 {% load toolbar_tags %}
-
 {% block title %}{{ document.name }} - {{ block.super }}{% endblock %}
-
 {% block extrahead %}
-       {% load compressed %}
-       {% compressed_css 'detail' %}
+{% load compressed %}
+{% compressed_css 'detail' %}
 {% endblock %}
-       
 {% block extrabody %}
-    <script type="text/javascript" charset="utf-8">
-        var STATIC_URL = '{{STATIC_URL}}';
-    </script>    
-    <script src="{{STATIC_URL}}js/lib/codemirror/codemirror.js" type="text/javascript" charset="utf-8"></script>
-       {% compressed_js 'detail' %}
+<script type="text/javascript" charset="utf-8">
+    var STATIC_URL = '{{STATIC_URL}}';
+</script>
+<script src="{{STATIC_URL}}js/lib/codemirror/codemirror.js" type="text/javascript" charset="utf-8">
+</script>
+{% compressed_js 'detail' %}
 {% endblock %}
-
 {% block maincontent %}
-        <div id="loading-overlay">
-            <div id="loading-message"><img src="{{STATIC_URL}}img/spinner.gif" /><p>Ładowanie</p></div>
-        </div>
-        <div id="document-meta" style="display:none">
-        {% for k, v in document.meta.items %}
-            <div class="{{ k }}">{{ v}}</div>
-        {% endfor %}
-        </div>
-        <div id="header">            
-            <h1><a href="{% url wiki.views.document_list %}">Platforma</a></h1>
-                       <div id="tools">
-                               <a href="{{ REDMINE_URL }}projects/wl-publikacje/wiki/Pomoc" target="_blank">Pomoc</a>                          
-                | {% include "registration/head_login.html" %} 
-                               | Wersja: <span id="document-revision">{{ document.revision }}</span> 
-                               | <button style="margin-left: 6px" id="save-button">Zapisz</button>
-                       </div>          
-            <ol id="tabs">
-                <li id="simple-view-tab" ui:related="simple-editor"><span id="document-name">{{ document.name }}</span></li>
-                <li id="source-view-tab" ui:related="source-editor">Kod źródłowy</li>
-                               <li id="history-view-tab" ui:related="history-viewer">Historia</li>
-            </ol>
-                         
+<div id="loading-overlay">
+    <div id="loading-message">
+        <img src="{{STATIC_URL}}img/spinner.gif" />
+        <p>
+            Ładowanie
+        </p>
+    </div>
+</div>
+
+<div id="document-meta" data-document-name="{{ document.name }}" style="display:none">
+{% for k, v in document.meta.items %}
+       <span data-key="{{ k }}">{{ v }}</span>
+{% endfor %}
+</div>
+
+<div id="header">
+    <h1><a href="{% url wiki.views.document_list %}">Platforma</a></h1>
+    <div id="tools">
+        <a href="{{ REDMINE_URL }}projects/wl-publikacje/wiki/Pomoc" target="_blank">Pomoc</a>
+        | {% include "registration/head_login.html" %} 
+        | Wersja: <span id="document-revision">{{ document.revision }}</span>
+        | 
+        <button style="margin-left: 6px" id="save-button">
+            Zapisz
+        </button>
+    </div>
+    <ol id="tabs">
+       <li id="HistoryPerspective-tab" 
+                       data-ui-related="history-viewer" 
+                       data-ui-jsclass="HistoryPerspective">           
+            Historia
+        </li>
+               
+        <li id="VisualPerspective-tab" 
+                       data-ui-related="simple-editor" data-ui-jsclass="VisualPerspective">
+            <span id="document-name">{{ document.name }}</span>
+        </li>
+                       
+               <li id="CodeMirrorPerspective-tab" 
+                       data-ui-related="source-editor" data-ui-jsclass="CodeMirrorPerspective">
+            Kod źródłowy
+        </li>
+    </ol>
+</div>
+<div id="splitter">
+    <div id="editor">
+        <div id="source-editor" class="editor">
+            {% toolbar %}
+            <textarea id="codemirror_placeholder">&lt;br/&gt;</textarea>
+            <input type="hidden" name="name" value="{{ document.name }}" /><input type="hidden" name="author" value="annonymous" /><input type="hidden" name="comment" value="no comment" /><input type="hidden" name="revision" value="{{ document.revision }}" />
         </div>
-        <div id="splitter">
-            <div id="editor">
-                <div id="source-editor" class="editor">
-                    {% toolbar %}
-                    <textarea name="text" id="id_text">{{ document.plain_text }}</textarea>
-                    <input type="hidden" name="name" value="{{ document.name }}" />
-                    <input type="hidden" name="author" value="annonymous" />
-                    <input type="hidden" name="comment" value="no comment" />
-                    <input type="hidden" name="revision" value="{{ document.revision }}" />
-                </div>
-                <div id="simple-editor" class="editor" style="display: none">                    
-                    <div id="html-view" class="htmlview">
-                    </div>
-                                       
-                                       <div class="toolbar">
-                        <button id="insert-theme-button">Wstaw motyw</button> <button id="insert-annotation-button">Wstaw przypis</button>
-                        <div class="toolbar-end"> </div>
-                    </div>
-                </div>
-                               
-                               <div id="history-viewer" class="editor" style="display: none">
-                                       <div class="toolbar"> </div>
-                                       <div id="history-view">
-                                               <p class="message-box" style="display:none;"></p>
-                                               <table>
-                                                       <thead>                 
-                                                               <th>&nbsp;</th>                                 
-                                                               <th>Numer</th>
-                                                               <th>Opis</th>
-                                                               <th>Użytkownik</th>
-                                                               <th>Data</th>
-                                                       </thead>
-                                                       <tbody id="changes-list">                                                                                                                               
-                                                       </tbody>
-                                               </table>
-                                               
-                                               <p><button type="button" id="make-diff-button">Porównaj</button></p>
-                                               <!-- <p><button type="button" id="more-history-button">Więcej</button></p> -->
-                                               <div id="diff-view">                                                                                                                                            
-                                       </div>                                                                  
-                               </div>                                                  
-                                                       
-                               </div>
+        <div id="simple-editor" class="editor" style="display: none">
+            <div id="html-view" class="htmlview">
             </div>
-            <div class="vsplitbar" title="Klinknij aby (ro)zwinąć galerię."> </div>
-            <div id="sidebar">
-                <div class="toolbar">
-                    <button class="previous-page">
-                       <img src="{{STATIC_URL}}icons/go-previous.png" alt="Poprzednia" title="Poprzednia"/>
-                    </button>
-                    <input type="text" size="3" maxlength="3" value="1" class="page-number" />
-                    <button class="next-page">
-                       <img src="{{STATIC_URL}}icons/go-next.png" alt="Następna" title="Następna"/>
-                    </button>
-                    <button class="zoom-in">Powiększ</button>
-                    <button class="zoom-out">Pomniejsz</button>
-                                       {% if request.user.is_staff %}
-                    <button class="change-gallery">Opcje</button>
-                                       {% endif %}
-                    <div class="toolbar-end"> </div>
-                </div>
-                               {% if request.user.is_staff %}
-                <div class="toolbar" id="change-gallery-toolbar">
-                    <input type="text" value="" class="chosen-gallery" />
-                    <button class="change-gallery-ok">Zmień galerię</button>
-                    <button class="change-gallery-cancel">Anuluj</button>
-                    <div class="toolbar-end"> </div>    
-                </div>
-                               {% endif %}
-                <div class="gallery-image">
-                    <img src="" />
+            <div class="toolbar">
+                <button id="insert-theme-button">
+                    Wstaw motyw
+                </button>
+                <button id="insert-annotation-button">
+                    Wstaw przypis
+                </button>
+                <div class="toolbar-end">
                 </div>
             </div>
         </div>
-        <div id="save-dialog" style="display: none; text-align: left">
-            <label for="komentarz" style="display: block">Opis zmian:</label>
-            <textarea name="komentarz" id="komentarz" style="display: block; width: 100%"></textarea>
-            <button id="save-ok">Zapisz</button> <button id="save-cancel">Anuluj</button>
+               {% include "wiki/history_panel.html" %}
+    </div>
+    <div class="vsplitbar" title="Klinknij aby (ro)zwinąć galerię."> </div>
+    <div id="sidebar">
+        <div class="toolbar">
+            <button class="previous-page">
+                <img src="{{STATIC_URL}}icons/go-previous.png" alt="Poprzednia" title="Poprzednia"/>
+            </button><input type="text" size="3" maxlength="3" value="1" class="page-number" />
+            <button class="next-page">
+                <img src="{{STATIC_URL}}icons/go-next.png" alt="Następna" title="Następna"/>
+            </button>
+            <button class="zoom-in">
+                Powiększ
+            </button>
+            <button class="zoom-out">
+                Pomniejsz
+            </button>
+            {% if request.user.is_staff %}
+            <button class="change-gallery">
+                Opcje
+            </button>
+            {% endif %}
+            <div class="toolbar-end">
+            </div>
+        </div>
+        {% if request.user.is_staff %}
+        <div class="toolbar" id="change-gallery-toolbar">
+            <input type="text" value="" class="chosen-gallery" />
+            <button class="change-gallery-ok">
+                Zmień galerię
+            </button>
+            <button class="change-gallery-cancel">
+                Anuluj
+            </button>
+            <div class="toolbar-end">
+            </div>
         </div>
+        {% endif %}
+        <div class="gallery-image"><img src="" /></div>
+    </div>
+</div>
+<div id="save-dialog" style="display: none; text-align: left">
+    <label for="komentarz" style="display: block">
+        Opis zmian:
+    </label>
+    <textarea name="komentarz" id="komentarz" style="display: block; width: 100%">
+    </textarea>
+    <button id="save-ok">
+        Zapisz
+    </button>
+    <button id="save-cancel">
+        Anuluj
+    </button>
+</div>
 {% endblock %}
\ No newline at end of file
diff --git a/apps/wiki/templates/wiki/history_panel.html b/apps/wiki/templates/wiki/history_panel.html
new file mode 100644 (file)
index 0000000..3edecde
--- /dev/null
@@ -0,0 +1,24 @@
+<div id="history-viewer" class="editor" style="display: none">
+    <div class="toolbar">
+    </div>
+    <div id="history-view">
+        <p class="message-box" style="display:none;">
+        </p>
+        <div class="row-stub" style="display: none;">
+            <span data-stub-value="version"></span>
+            <input type="checkbox" name="revision" data-stub-value="version" data-stub-target="value"><span data-stub-value="description"></span>
+            <span data-stub-value="author"></span>
+            <span data-stub-value="date"></span>
+        </div>
+        <div id="changes-list">
+        </div>
+        <p>
+            <button type="button" id="make-diff-button">
+                Porównaj
+            </button>
+        </p>
+        <!-- <p><button type="button" id="more-history-button">Więcej</button></p> -->
+        <div id="diff-view">
+        </div>
+    </div>
+</div>
index d403b76..14cb81e 100644 (file)
@@ -7,6 +7,8 @@ urlpatterns = patterns('wiki.views',
         'document_gallery', name="wiki_gallery"),
     url(r'^(?P<name>[^/]+)/history$', 
         'document_history', name="wiki_history"),
+    url(r'^(?P<name>[^/]+)/text$', 
+        'document_text', name="wiki_text"),
     url(r'^(?P<name>[^/]+)/publish/(?P<version>\d+)$', 
         'document_publish', name="wiki_publish"),
     url(r'^(?P<name>[^/]+)/diff/(?P<revA>\d+)/(?P<revB>\d+)$', 
index 78a1942..c3fd6e3 100644 (file)
@@ -9,6 +9,7 @@ from wiki.models import Document, DocumentNotFound, getstorage
 from wiki.forms import DocumentForm
 from datetime import datetime
 from django.utils.encoding import smart_unicode
+import wlapi
 
 #
 # Quick hack around caching problems, TODO: use ETags
@@ -40,7 +41,7 @@ def document_list(request, template_name = 'wiki/document_list.html'):
 
 @never_cache
 def document_detail(request, name, template_name = 'wiki/document_details.html'):
-    print "Trying to get", repr(name)
+    
     try:
         document = getstorage().get(name)
     except DocumentNotFound:        
@@ -53,8 +54,19 @@ def document_detail(request, name, template_name = 'wiki/document_details.html')
     if len(last_documents) > MAX_LAST_DOCS:
         oldest_key = min(last_documents, key = last_documents.__getitem__)
         del last_documents[oldest_key]        
-    request.session['wiki_last_docs'] = last_documents   
-                
+    request.session['wiki_last_docs'] = last_documents      
+
+    return direct_to_template(request, template_name, extra_context = {
+        'document': document,        
+    })
+
+@never_cache
+def document_text(request, name):
+    try:
+        document = getstorage().get(name)
+    except DocumentNotFound:        
+        raise Http404
+    
     if request.method == 'POST':        
         form = DocumentForm(request.POST, instance = document)
         if form.is_valid():
@@ -63,12 +75,8 @@ def document_detail(request, name, template_name = 'wiki/document_details.html')
         else:
             return HttpResponse(json.dumps({'errors': form.errors}))
     else:
-        form = DocumentForm(instance = document)
-
-    return direct_to_template(request, template_name, extra_context = {
-        'document': document,
-        'form': form,
-    })
+        return HttpResponse(json.dumps({'text': document.plain_text, 'meta': document.meta(), 'revision': document.revision()}))
+   
 
 
 @never_cache
@@ -119,8 +127,6 @@ def document_history(request, name):
                 mimetype='application/json')
     
     
-import urllib, urllib2
-
 @never_cache
 def document_publish(request, name, version):
     storage = getstorage()
@@ -131,25 +137,10 @@ def document_publish(request, name, version):
     except DocumentNotFound:        
         raise Http404
     
-    auth_handler = urllib2.HTTPDigestAuthHandler();
-    auth_handler.add_password(
-                    realm="localhost:8000",
-                    uri="http://localhost:8000/api/",
-                    user="test", passwd="test")
-    
-    
-    opener = urllib2.build_opener(auth_handler)         
-    rq = urllib2.Request("http://localhost:8000/api/books.json")
-    rq.add_data(json.dumps({"text": document.text, "compressed": False}))
-    rq.add_header("Content-Type", "application/json")
-    
-    try:
-        response = opener.open(rq)                 
-        result = {"success": True, "message": response.read()}        
-    except urllib2.HTTPError, e:
-        logger.exception("Failed to send")
-        if e.code == 500:
-            return HttpResponse(e.read(), mimetype='text/plain')                        
-        result = {"success": False, "reason": e.read(), "errno": e.code}
+    api = wlapi.WLAPI(settings.WL_API_CONFIG)    
+    try:        
+        result = {"success": True, "result": api.publish_book(document)}
+    except wlapi.APICallException, e:                        
+        result = {"success": False, "reason": str(e)}
         
     return HttpResponse( json.dumps(result), mimetype='application/json')       
\ No newline at end of file
index 7a80c9b..02f0503 100644 (file)
@@ -350,7 +350,7 @@ class VersionedStorage(object):
             author = unicode(filectx.user(), "utf-8",
                              'replace').split('<')[0].strip()
             comment = unicode(filectx.description(), "utf-8", 'replace')
-            yield rev, date, author, comment
+            yield {"version": rev, "date": date, "author": author, "description": comment}
 
     def page_revision(self, title, rev):
         """Get unicode contents of specified revision of the page."""
diff --git a/lib/wlapi.py b/lib/wlapi.py
new file mode 100644 (file)
index 0000000..6f49dfe
--- /dev/null
@@ -0,0 +1,70 @@
+"""
+   Abstraction over API for wolnelektury.pl
+"""
+import urllib2
+import functools
+import django.utils.simplejson as json
+import logging
+logger = logging.getLogger("fnp.lib.wlapi")
+
+class APICallException(Exception):
+    pass 
+
+def api_call(path, format="json"):
+    def wrapper(func):
+        
+        @functools.wraps(func)
+        def wrapped(self, *args, **kwargs):            
+            generator = func(self, *args, **kwargs)
+            
+            data = generator.next()
+            
+            # prepare request
+            rq = urllib2.Request(self.base_url + path + ".json")
+            
+            # will send POST when there is data, GET otherwise
+            if data is not None:
+                rq.add_data(json.dumps(data))    
+                rq.add_header("Content-Type", "application/json")
+                            
+            try:
+                anwser = json.load(self.opener.open(rq))
+                return generator.send(anwser)
+            except StopIteration:
+                # by default, just return the anwser as a shorthand
+                return anwser                            
+            except urllib2.HTTPError, error:
+                return self._http_error(error)         
+            except Exception, error:
+                return self._error(error)               
+        return wrapped
+    
+    return wrapper
+         
+    
+
+class WLAPI(object):
+    
+    def __init__(self, config_dict):        
+        self.base_url = config_dict['URL']
+        self.auth_realm = config_dict['AUTH_REALM']
+        self.auth_user = config_dict['AUTH_USER'] 
+        
+        auth_handler = urllib2.HTTPDigestAuthHandler();
+        auth_handler.add_password(
+                    realm=self.auth_realm, uri=self.base_url,
+                    user=self.auth_user, passwd=config_dict['AUTH_PASSWD'])
+        
+        self.opener = urllib2.build_opener(auth_handler)
+        
+    def _http_error(self, error):
+        return self._error()
+    
+    def _error(self, error):
+        raise APICallException(cause = error) 
+        
+    @api_call("books")
+    def publish_book(self, document):
+        yield {"text": document.text, "compressed": False} 
+        
+    
\ No newline at end of file
index 0fb6518..5485b30 100644 (file)
@@ -113,7 +113,8 @@ CAS_LOGOUT_COMPLETELY = True
 COMPRESS_CSS = {
     'detail': {
          'source_filenames': (
-            'css/master.css', 
+            'css/master.css',
+            'css/history.css', 
             'css/html.css',             
             'css/jquery.autocomplete.css',
         ),
@@ -137,8 +138,15 @@ COMPRESS_JS = {
                 'js/jquery.elastic.js',
                 'js/button_scripts.js',
                 'js/slugify.js',
-                'js/xslt.js',
-                'js/main.js',
+                
+                # wiki scripts
+                'js/wiki/wikiapi.js',
+                'js/wiki/base.js',
+                'js/wiki/xslt.js',
+                'js/wiki/history.js',
+                'js/wiki/source_editor.js',
+                'js/wiki/wysiwyg_editor.js',                
+                'js/wiki/main.js',
         ),             
         'output_filename': 'compressed/detail_scripts_?.js',
      },
diff --git a/platforma/static/css/history.css b/platforma/static/css/history.css
new file mode 100644 (file)
index 0000000..26ab7f9
--- /dev/null
@@ -0,0 +1,59 @@
+#history-view .diff_table {
+       width: 90%;
+}
+/* DIFFS */
+ .diff_table { 
+       border-width: 1px;
+       border-style: solid;
+       border-color: black;
+       empty-cells: show;
+       border-spacing: 0px;            
+}
+
+.diff_table td {
+       border-width: 0px 1px 1px 0px;
+       border-style: dotted;
+       border-color: grey;
+       
+       font-size: 10px;
+       line-height: 20px;
+       font-family: monospace;
+       padding: 0px;
+       white-space:pre-line;
+       /*word-wrap:break-word;
+       word-break:break-all; */
+}
+
+.diff_table th {
+       border-width: 0px 1px 1px 0px;
+       border-style: solid;
+       border-color: black;
+       background: #e5ffe5;            
+}
+/* .diff_table td.left, .diff_table td.right {
+       width: 50%;
+}*/
+
+.diff_table tr.change {
+       background-color: #dcdcdc;
+       
+}
+
+.diff_mark {
+       display: inline-block;
+       padding: 2px;
+}
+
+.diff_mark_removed {
+       background-color: #ff9c94;
+}
+
+.diff_mark_added {
+       background-color: #90ee90;
+}
+
+.diff_mark_changed {
+       background-color: yellow;
+}
\ No newline at end of file
index d41a73c..b1bcdf7 100644 (file)
@@ -332,70 +332,7 @@ p { margin: 0;}
        padding-right: 5px;
 }
 
-#history-view table {
-       width: 80%;
-       margin: 1em auto;       
-}
-
-#history-view .diff_table {
-       width: 90%;
-}
-/* DIFFS */
- .diff_table { 
-       border-width: 1px;
-       border-style: solid;
-       border-color: black;
-       empty-cells: show;
-       border-spacing: 0px;            
-}
-
-.diff_table td {
-       border-width: 0px 1px 1px 0px;
-       border-style: dotted;
-       border-color: grey;
-       
-       font-size: 10px;
-       line-height: 20px;
-       font-family: monospace;
-       padding: 0px;
-       white-space:pre-line;
-       /*word-wrap:break-word;
-       word-break:break-all; */
-}
-
-.diff_table th {
-       border-width: 0px 1px 1px 0px;
-       border-style: solid;
-       border-color: black;
-       background: #e5ffe5;            
-}
-/* .diff_table td.left, .diff_table td.right {
-       width: 50%;
-}*/
 
-.diff_table tr.change {
-       background-color: #dcdcdc;
-       
-}
-
-.diff_mark {
-       display: inline-block;
-       padding: 2px;
-}
-
-.diff_mark_removed {
-       background-color: #ff9c94;
-}
-
-.diff_mark_added {
-       background-color: #90ee90;
-}
-
-.diff_mark_changed {
-       background-color: yellow;
-}
 /*
  * HTML Editor view
  */ 
diff --git a/platforma/static/js/main.js b/platforma/static/js/main.js
deleted file mode 100644 (file)
index f94e04e..0000000
+++ /dev/null
@@ -1,904 +0,0 @@
-if (!window.console) {
-    window.console = {
-        log: function() {}
-    }
-}
-
-THEMES = ['Alkohol', 'Ambicja', 'Anioł', 'Antysemityzm', 'Arkadia', 'Artysta', 'Bezdomność',
-'Bezpieczeństwo', 'Bieda', 'Bijatyka', 'Błazen', 'Błądzenie', 'Błoto', 'Bogactwo', 'Bóg', 'Brat',
-'Bunt', 'Buntownik', 'Burza', 'Car', 'Carpe diem', 'Ciemność', 'Cień', 'Cisza', 'Chciwość', 'Chleb',
-'Chłop', 'Choroba', 'Chrystus', 'Chrzest', 'Ciało', 'Cierpienie', 'Cmentarz', 'Cnota', 'Córka', 'Cud',
-'Czarownika', 'Czary', 'Czas', 'Czyn', 'Czyściec', 'Dama', 'Danse macabre', 'Deszcz', 'Diabeł',
-'Dobro', 'Dom', 'Dorosłość', 'Drzewo', 'Duch', 'Dusza', 'Duma', 'Dworek', 'Dworzanin', 'Dwór',
-'Dzieciństwo', 'Dziecko', 'Dziedzictwo', 'Dziewictwo', 'Dźwięk', 'Egzorcyzm', 'Elita', 'Emigrant',
-'Fałsz', 'Filozof', 'Fircyk', 'Flirt', 'Głupiec', 'Głupota', 'Głód', 'Gospodarz', 'Gospodyni', 'Gość',
-'Gotycyzm', 'Góra', 'Gra', 'Grób', 'Grzech', 'Grzeczność', 'Gwiazda', 'Handel', 'Hańba', 'Historia',
-'Honor', 'Idealista', 'Imię', 'Interes', 'Jabłka', 'Jedzenie', 'Jesień', 'Kaleka', 'Kara', 'Karczma',
-'Klęska', 'Kłamstwo', 'Kłótnia', 'Kobieta', 'Kobieta demoniczna', 'Kobieta "upadła"', 'Kochanek',
-'Kochanek romantyczny', 'Kolonializm', 'Kondycja ludzka', 'Konflikt', 'Konflikt wewnętrzny', 'Koniec świata',
-'Koń', 'Korzyść', 'Kot', 'Kradzież', 'Krew', 'Król', 'Krzywda', 'Ksiądz', 'Książka',
-'Księżyc', 'Kuchnia', 'Kuszenie', 'Kwiaty', 'Labirynt', 'Las', 'Lato', 'Lekarz', 'Lenistwo', 'List',
-'Liberat', 'Los', 'Lud', 'Lustro', 'Łzy', 'Małżeństwo', 'Marzenie', 'Maska', 'Maszyna', 'Matka',
-'Matka Boska', 'Mądrość', 'Mąż', 'Melancholia', 'Mędrzec', 'Mężczyzna', 'Miasto', 'Mieszczanin',
-'Miłosierdzie', 'Miłość', 'Miłość niespełniona', 'Miłość platoniczna', 'Miłość romantyczna', 
-'Miłość silniejsza niż śmierć', 'Miłość spełniona', 'Miłość tragiczna', 'Mizoginia', 'Młodość', 'Moda',
-'Modlitwa', 'Morderstwo', 'Morze', 'Motyl', 'Mucha', 'Muzyka', 'Narodziny', 'Naród', 'Natura',
-'Nauczyciel', 'Nauczycielka', 'Nauka', 'Niebezpieczeństwo', 'Niedziela', 'Niemiec', 'Nienawiść',
-'Nieśmiertelność', 'Niewola', 'Noc', 'Nuda', 'Obcy', 'Obłok', 'Obowiązek', 'Obraz świata', 'Obrzędy',
-'Obyczaje', 'Obywatel', 'Odrodzenie przez grób', 'Odwaga', 'Ofiara', 'Ogień', 'Ogród', 'Ojciec',
-'Ojczyzna', 'Oko', 'Okręt', 'Okrucieństwo', 'Omen', 'Opieka', 'Organizm', 'Otchłań', 'Pająk', 'Pamięć',
-'Pan', 'Panna młoda', 'Państwo', 'Patriota', 'Piekło', 'Pielgrzym', 'Pieniądz', 'Pies', 'Piętno',
-'Pijaństwo', 'Piwnica', 'Plotka', 'Pobożność', 'Pocałunek', 'Pochlebstwo', 'Poeta', 'Poetka', 'Poezja',
-'Podróż', 'Podstęp', 'Pogrzeb', 'Pojedynek', 'Pokora', 'Pokusa', 'Polak', 'Polityka', 'Polowanie',
-'Polska', 'Portret', 'Porwanie', 'Poświęcenie', 'Potwór', 'Powstanie', 'Powstaniec', 'Pozory',
-'Pozycja społeczna', 'Pożar', 'Pożądanie', 'Praca', 'Praca u podstaw', 'Praca organiczna', 'Prawda', 'Prawnik',
-'Prometeusz', 'Proroctwo', 'Prorok', 'Próżność', 'Przebranie', 'Przeczucie', 'Przedmurze chrześcijaństwa',
-'Przekleństwo', 'Przekupstwo', 'Przemiana', 'Przemijanie', 'Przemoc', 'Przestrzeń',
-'Przyjaźń', 'Przyroda nieożywiona', 'Przysięga', 'Przywódca', 'Ptak', 'Pustynia', 'Pycha', 'Raj',
-'Realista', 'Religia', 'Rewolucja', 'Robak', 'Robotnik', 'Rodzina', 'Rosja', 'Rosjanin', 'Rośliny',
-'Rozczarowanie', 'Rozpacz', 'Rozstanie', 'Rozum', 'Ruiny', 'Rycerz', 'Rzeka', 'Salon', 'Samobójstwo',
-'Samolubstwo', 'Samotnik', 'Samotność', 'Sarmata', 'Sąsiad', 'Sąd', 'Sąd Ostateczny', 'Sen', 'Serce',
-'Sędzia', 'Sielanka', 'Sierota', 'Siła', 'Siostra', 'Sława', 'Słońce', 'Słowo', 'Sługa', 'Służalczość',
-'Skąpiec', 'Sobowtór', 'Społecznik', 'Spowiedź', 'Sprawiedliwość', 'Starość', 'Strach', 'Strój',
-'Stworzenie', 'Sumienie', 'Swaty', 'Syberia', 'Syn', 'Syn marnotrawny', 'Syzyf', 'Szaleniec',
-'Szaleństwo', 'Szantaż', 'Szatan', 'Szczęście', 'Szkoła', 'Szlachcic', 'Szpieg', 'Sztuka', 'Ślub',
-'Śmiech', 'Śmierć', 'Śmierć bohaterska', 'Śpiew', 'Światło', 'Świętoszek', 'Święty', 'Świt',
-'Tajemnica', 'Taniec', 'Tchórzostwo', 'Teatr', 'Testament', 'Tęsknota', 'Theatrum mundi', 'Tłum',
-'Trucizna', 'Trup', 'Twórczość', 'Uczeń', 'Uczta', 'Uroda', 'Umiarkowanie', 'Upadek', 'Upiór',
-'Urzędnik', 'Vanitas', 'Walka', 'Walka klas', 'Wampir', 'Warszawa', 'Wąż', 'Wdowa', 'Wdowiec',
-'Wesele', 'Wiatr', 'Wierność', 'Wierzenia', 'Wieś', 'Wiedza', 'Wieża Babel', 'Więzienie', 'Więzień',
-'Wina', 'Wino', 'Wiosna', 'Wizja', 'Władza', 'Własność', 'Woda', 'Wojna', 'Wojna pokoleń', 'Wolność',
-'Wróg', 'Wspomnienia', 'Współpraca', 'Wygnanie', 'Wyrzuty sumienia', 'Wyspa', 'Wzrok', 'Zabawa',
-'Zabobony', 'Zamek', 'Zaręczyny', 'Zaświaty', 'Zazdrość', 'Zbawienie', 'Zbrodnia', 'Zbrodniarz',
-'Zdrada', 'Zdrowie', 'Zemsta', 'Zesłaniec', 'Ziarno', 'Ziemia', 'Zima', 'Zło', 'Złodziej', 'Złoty wiek',
-'Zmartwychwstanie', 'Zwątpienie', 'Zwierzęta', 'Zwycięstwo', 'Żałoba', 'Żebrak', 'Żołnierz',
-'Żona', 'Życie jako wędrówka', 'Życie snem', 'Żyd', 'Żywioły', 'Oświadczyny']
-
-
-// Teraz nieużywane
-function highlight(colour) {
-    var range, sel;
-    if (window.getSelection) {
-        // Non-IE case
-        sel = window.getSelection();
-        if (sel.getRangeAt) {
-            range = sel.getRangeAt(0);
-        }
-        document.designMode = "on";
-        if (range) {
-            sel.removeAllRanges();
-            sel.addRange(range);
-        }
-        // Use HiliteColor since some browsers apply BackColor to the whole block
-        if ( !document.execCommand("HiliteColor", false, colour) ) {
-            document.execCommand("BackColor", false, colour);
-        }
-        document.designMode = "off";
-    } else if (document.selection && document.selection.createRange) {
-        // IE case
-        range = document.selection.createRange();
-        range.execCommand("BackColor", false, colour);
-    }
-}
-
-// function unselectThemes(themeId) {
-//     $('.Apple-style-span').each(function() {
-//         $(this).after($(this).html());
-//         $(this).remove();
-//     });
-// }
-
-function gallery(element, url) {    
-    var element = $(element);
-    var imageDimensions = {};
-    element.data('images', []);
-    
-    function changePage(pageNumber) {        
-        $('.gallery-image img', element).attr('src', element.data('images')[pageNumber - 1]);
-    }
-    
-    function normalizeNumber(pageNumber) {
-        // Numer strony musi być pomiędzy 1 a najwyższym numerem
-        var pageCount = element.data('images').length;
-        pageNumber = parseInt(pageNumber, 10);
-        
-        if (!pageNumber || pageNumber == NaN || pageNumber == Infinity || pageNumber == -Infinity) {
-            return 1;
-        } else if (pageNumber < 1) {
-            return 1;
-        } else if (pageNumber > pageCount) {
-            return pageCount;
-        } else {
-            return pageNumber;
-        }
-    }
-    
-    var pn = $('.page-number', element);
-    pn.change(function(event) {
-        event.preventDefault();
-        var n = normalizeNumber(pn.val());
-        pn.val(n);
-        changePage(n);
-    });
-    $('.previous-page', element).click(function() {
-        pn.val(normalizeNumber(pn.val()) - 1);
-        pn.change();
-    });
-    $('.next-page', element).click(function() {
-        pn.val(normalizeNumber(pn.val()) + 1);
-        pn.change();
-    });
-    
-    
-    var image = $('.gallery-image img', element).attr('unselectable', 'on');
-    var origin = {};
-    var imageOrigin = {};
-    var zoomFactor = 1;
-    
-    $('.zoom-in', element).click(function() {
-        zoomFactor = Math.min(2, zoomFactor + 0.2);
-        zoom();
-    });
-    $('.zoom-out', element).click(function() {
-        zoomFactor = Math.max(0.2, zoomFactor - 0.2);
-        zoom();
-    });
-    $('.change-gallery', element).click(function() {
-        $('.chosen-gallery').val($('#document-meta .gallery').html() || '/platforma/gallery/');
-        $('.gallery-image').animate({top: 60}, 200);
-        $('.chosen-gallery').focus();
-    });
-    $('.change-gallery-ok', element).click(function() {
-        if ($('#document-meta .gallery').length == 0) {
-            $('<div class="gallery"></div>').appendTo('#document-meta');
-        }
-        $('#document-meta .gallery').html($('.chosen-gallery').val());
-        updateGallery($('.chosen-gallery').val());
-        $('.gallery-image').animate({top: 30}, 200);
-    });
-    $('.change-gallery-cancel', element).click(function() {
-        $('.gallery-image').animate({top: 30}, 200);
-    });
-    
-    $('.gallery-image img', element).load(function() {
-        image.css({width: null, height: null});
-        imageDimensions = {
-            width: $(this).width() * zoomFactor,
-            height: $(this).height() * zoomFactor,
-            originWidth: $(this).width(),
-            originHeight: $(this).height(),
-            galleryWidth: $(this).parent().width(),
-            galleryHeight: $(this).parent().height()
-        };
-        
-        if (!(imageDimensions.width && imageDimensions.height)) {
-            setTimeout(function() { $('.gallery-image img', element).load(); }, 100);
-        }        
-        var position = normalizePosition(
-            image.position().left,
-            image.position().top, 
-            imageDimensions.galleryWidth,
-            imageDimensions.galleryHeight,
-            imageDimensions.width,
-            imageDimensions.height
-        );
-        image.css({left: position.x, top: position.y, width: $(this).width() * zoomFactor, height: $(this).height() * zoomFactor});
-    });
-
-    $(window).resize(function() {
-        imageDimensions.galleryWidth = image.parent().width();
-        imageDimensions.galleryHeight = image.parent().height();
-    });
-    
-    function bounds(galleryWidth, galleryHeight, imageWidth, imageHeight) {
-        return {
-            maxX: 0,
-            maxY: 0,
-            minX: galleryWidth - imageWidth,
-            minY: galleryHeight - imageHeight
-        }
-    }
-    
-    function normalizePosition(x, y, galleryWidth, galleryHeight, imageWidth, imageHeight) {
-        var b = bounds(galleryWidth, galleryHeight, imageWidth, imageHeight);
-        return {
-            x: Math.min(b.maxX, Math.max(b.minX, x)),
-            y: Math.min(b.maxY, Math.max(b.minY, y))
-        }
-    }
-    
-    function onMouseMove(event) {
-        var position = normalizePosition(
-            event.clientX - origin.x + imageOrigin.left,
-            event.clientY - origin.y + imageOrigin.top, 
-            imageDimensions.galleryWidth,
-            imageDimensions.galleryHeight,
-            imageDimensions.width,
-            imageDimensions.height
-        );
-        image.css({position: 'absolute', top: position.y, left: position.x});
-        return false;
-    }
-    
-    function setZoom(factor) {
-        zoomFactor = factor;
-    }
-    
-    function zoom() {
-        imageDimensions.width = imageDimensions.originWidth * zoomFactor;
-        imageDimensions.height = imageDimensions.originHeight * zoomFactor;
-        var position = normalizePosition(
-            image.position().left,
-            image.position().top, 
-            imageDimensions.galleryWidth,
-            imageDimensions.galleryHeight,
-            imageDimensions.width,
-            imageDimensions.height
-        );
-        image.css({width: imageDimensions.width, height: imageDimensions.height,
-            left: position.x, top: position.y});
-
-    }
-    
-    function onMouseUp(event) {
-        $(document)
-            .unbind('mousemove.gallery')
-            .unbind('mouseup.gallery');
-        return false;
-    }
-    
-    image.bind('mousedown', function(event) {
-        origin = {
-            x: event.clientX,
-            y: event.clientY
-        };
-        imageOrigin = image.position();
-        $(document)
-            .bind('mousemove.gallery', onMouseMove)
-            .bind('mouseup.gallery', onMouseUp);
-        return false;
-    });
-    
-    function updateGallery(url) {
-        $.ajax({
-            url: url,
-            type: 'GET',
-            dataType: 'json',
-
-            success: function(data) {
-                element.data('images', data);
-                pn.val(1);
-                pn.change();
-                $('.gallery-image img', element).show();
-            },
-            
-            error: function(data) {
-                element.data('images', []);
-                pn.val(1);
-                pn.change();
-                $('.gallery-image img', element).hide();
-            }
-        });
-    }
-    
-    if (url) {
-        updateGallery(url);
-    }
-}
-
-
-function transform(editor, callback) {
-    if (!callback) {
-        $.blockUI({message: 'Ładowanie...'});
-    }
-    setTimeout(function() {
-        xml2html({
-            xml: editor.getCode(),
-            success: function(element) {
-                $('#html-view').html(element);
-                $.unblockUI();
-                if (callback) {
-                    callback();
-                }
-            }, error: function(text) {
-                               var message = $('<pre></pre>');
-                               message.text(text);
-                $('#html-view').html('<p class="error">Wystąpił błąd:</p><pre>' + 
-                                   message.html() + '</pre>');
-                                       
-                $.unblockUI();
-                if (callback) {
-                    callback();
-                }
-            }
-        });
-    }, 200);
-};
-
-
-function reverseTransform(editor, cont, errorCont, dontBlock) {
-    var serializer = new XMLSerializer();
-    if ($('#html-view .error').length > 0) {
-        if (errorCont) {
-            errorCont();
-        }
-        return;
-    }
-    if (!dontBlock) {
-        $.blockUI({message: 'Ładowanie...'});
-    }
-    setTimeout(function() {
-        html2text({
-                       element: $('#html-view div').get(0),            
-            success: function(text) {
-                editor.setCode(text);
-                if (!dontBlock) {
-                    $.unblockUI();
-                }
-                if (cont) {
-                    cont();
-                }
-            }, error: function(text) {
-                $('#source-editor').html('<p>Wystąpił błąd:</p><pre>' + text + '</pre>');
-                if (!dontBlock) {
-                    $.unblockUI();
-                }
-                if (errorCont) {
-                    errorCont();
-                }
-            }
-        });
-    }, 200);
-}
-
-
-// =============
-// = HTML View =
-// =============
-function html(element) {
-    var element = $(element);
-    
-    function selectTheme(themeId)
-    {
-        var selection = window.getSelection();
-        selection.removeAllRanges();
-
-        var range = document.createRange();
-        var s = $(".motyw[theme-class='"+themeId+"']")[0];
-        var e = $(".end[theme-class='"+themeId+"']")[0];
-
-        if(s && e) {
-            range.setStartAfter(s);
-            range.setEndBefore(e);
-            selection.addRange(range);
-        }
-    };
-    
-    function verifyTagInsertPoint(node) {
-        if(node.nodeType == 3) { // Text Node
-            node = node.parentNode;
-        }
-
-        if (node.nodeType != 1) { 
-            return false;
-        }
-
-        node = $(node);
-        var xtype = node.attr('x-node');
-
-        if (!xtype || (xtype.search(':') >= 0) ||
-            xtype == 'motyw' || xtype == 'begin' || xtype == 'end') {
-            return false;
-        }
-        
-        // don't allow themes inside annotations
-        if( node.is('*[x-annotation-box] *') )
-            return false;
-
-        return true;
-    }
-       
-       var ANNOT_ALLOWED = ['wyroznienie', 'slowo_obce', 'osoba'];
-       
-       function html2plainText(fragment) {
-               var text = "";
-               
-               $(fragment.childNodes).each(function() {
-                       if(this.nodeType == 3) // textNode
-                           text += this.nodeValue;
-                       else if (this.nodeType == 1 
-                           && $.inArray($(this).attr('x-node'), ANNOT_ALLOWED) != -1 ){
-                               text += html2plainText(this);                           
-                       }                       
-               });
-               
-               return text;            
-       }
-    
-    function addAnnotation()
-    {
-        var selection = window.getSelection();
-        var n = selection.rangeCount;
-
-        if (n == 0) {
-            window.alert("Nie zaznaczono żadnego obszaru");
-            return false;
-        }
-
-        // for now allow only 1 range
-        if (n > 1) {
-            window.alert("Zaznacz jeden obszar");
-            return false;
-        }
-
-        // remember the selected range
-        var range = selection.getRangeAt(0);
-
-        if (!verifyTagInsertPoint(range.endContainer)) {
-            window.alert("Nie można wstawić w to miejsce przypisu.");
-            return false;
-        }
-
-               // BUG #273 - selected text can contain themes, which should be omited from
-               // defining term
-        var text = html2plainText( range.cloneContents() ); 
-               
-        var tag = $('<span></span>');
-        range.collapse(false);
-        range.insertNode(tag[0]);
-
-        xml2html({
-            xml: '<pr><slowo_obce>'+text+'</slowo_obce> --- </pr>',
-            success: function(text) {
-                var t = $(text);
-                tag.replaceWith(t);
-                openForEdit(t);
-            },
-            error: function() {
-                tag.remove();
-                alert('Błąd przy dodawaniu przypisu:' + errors);                
-            }
-        })
-    }
-    
-    function addTheme()
-    {
-        var selection = window.getSelection();
-        var n = selection.rangeCount;
-
-        if(n == 0) {
-            window.alert("Nie zaznaczono żadnego obszaru");
-            return false;
-        }
-
-        // for now allow only 1 range
-        if(n > 1) {
-            window.alert("Zaznacz jeden obszar.");
-            return false;
-        }
-                
-
-        // remember the selected range
-        var range = selection.getRangeAt(0);
-               
-               
-               if( $(range.startContainer).is('.html-editarea') 
-                || $(range.endContainer).is('.html-editarea') ) {
-                       window.alert("Motywy można oznaczać tylko na tekście nie otwartym do edycji. \n Zamknij edytowany fragment i spróbuj ponownie.");
-            return false;
-                }               
-
-        // verify if the start/end points make even sense -
-        // they must be inside a x-node (otherwise they will be discarded)
-        // and the x-node must be a main text
-        if (!verifyTagInsertPoint(range.startContainer)) {
-            window.alert("Motyw nie może się zaczynać w tym miejscu.");
-            return false;
-        }
-
-        if (!verifyTagInsertPoint(range.endContainer)) {
-            window.alert("Motyw nie może się kończyć w tym miejscu.");
-            return false;
-        }
-
-        var date = (new Date()).getTime();
-        var random = Math.floor(4000000000*Math.random());
-        var id = (''+date) + '-' + (''+random);
-
-        var spoint = document.createRange();
-        var epoint = document.createRange();
-
-        spoint.setStart(range.startContainer, range.startOffset);
-        epoint.setStart(range.endContainer, range.endOffset);
-
-        var mtag, btag, etag, errors;
-
-        // insert theme-ref
-                
-        xml2html({
-            xml: '<end id="e'+id+'" />',
-            success: function(text) {
-                etag = $('<span></span>');
-                epoint.insertNode(etag[0]);
-                etag.replaceWith(text);
-                xml2html({
-                    xml: '<motyw id="m'+id+'"></motyw>',
-                    success: function(text) {                                          
-                        mtag = $('<span></span>');
-                        spoint.insertNode(mtag[0]);
-                        mtag.replaceWith(text);
-                        xml2html({
-                            xml: '<begin id="b'+id+'" />',
-                            success: function(text) {
-                                btag = $('<span></span>');
-                                spoint.insertNode(btag[0])
-                                btag.replaceWith(text);
-                                selection.removeAllRanges();
-                                openForEdit($('.motyw[theme-class=' + id + ']'));
-                            }
-                        });
-                    }
-                });
-            }
-        });
-    }
-    
-    function openForEdit($origin)
-    {       
-        var $box = null
-    
-        // annotations overlay their sub box - not their own box //
-        if($origin.is(".annotation-inline-box")) {
-            $box = $("*[x-annotation-box]", $origin);
-        } else {
-            $box = $origin;
-        }
-        
-        var x = $box[0].offsetLeft;
-        var y = $box[0].offsetTop;
-        var w = $box.outerWidth();
-        var h = $box.innerHeight();
-    
-        if ($origin.is(".annotation-inline-box")) {
-            w = Math.max(w, 400);
-            h = Math.max(h, 60);
-        }
-        
-        // start edition on this node
-        var $overlay = $('<div class="html-editarea"><button class="accept-button">Zapisz</button><button class="delete-button">Usuń</button><textarea></textarea></div>').css({
-            position: 'absolute',
-            height: h,
-            left: x,
-            top: y,
-            width: w
-        }).appendTo($box[0].offsetParent || $box.parent()).show();
-        
-        if ($origin.is('.motyw')) {
-            $('textarea', $overlay).autocomplete(THEMES, {
-                autoFill: true,
-                multiple: true,
-                selectFirst: true
-            });
-        }
-        
-        $('.delete-button', $overlay).click(function() {
-            if ($origin.is('.motyw')) {
-                $('[theme-class=' + $origin.attr('theme-class') + ']').remove();
-            } else {
-                $origin.remove();
-            }
-            $overlay.remove();
-            $(document).unbind('click.blur-overlay');
-            return false;
-        })
-        
-        
-        var serializer = new XMLSerializer();
-        
-        html2text({
-            element: $box[0],
-            stripOuter: true,
-            success: function(text) {
-                $('textarea', $overlay).val($.trim(text));
-                
-                setTimeout(function() {
-                    $('textarea', $overlay).elastic().focus();
-                }, 50);
-                
-                function save(argument) {
-                    var nodeName = $box.attr('x-node') || 'pe';
-                                       var insertedText = $('textarea', $overlay).val();
-                                       
-                                       if ($origin.is('.motyw')) {
-                                               insertedText = insertedText.replace(/,\s*$/, '');
-                                       }
-                                       
-                    xml2html({
-                        xml: '<' + nodeName + '>' + insertedText + '</' + nodeName + '>',
-                        success: function(element) {
-                            $origin.html($(element).html());
-                            $overlay.remove();
-                        },
-                        error: function(text) {
-                            $overlay.remove();
-                            alert('Błąd! ' + text);
-                        }
-                    })
-                }
-                
-                $('.accept-button', $overlay).click(function() {
-                    save();
-                });
-                
-                $(document).bind('click.blur-overlay', function(event) {
-                    if ($(event.target).parents('.html-editarea').length > 0) {
-                        return;
-                    }
-                    save();
-                    
-                    $(document).unbind('click.blur-overlay');
-                });
-                
-            }, error: function(text) {
-                alert('Błąd! ' + text);
-            }
-        });
-    }
-    
-    $('.edit-button').live('click', function(event) {
-        event.preventDefault();
-        openForEdit($(this).parent());
-    });
-    
-
-    
-    var button = $('<button class="edit-button">Edytuj</button>');
-    $(element).bind('mousemove', function(event) {
-        var editable = $(event.target).closest('*[x-editable]');
-        $('.active[x-editable]', element).not(editable).removeClass('active').children('.edit-button').remove();
-        if (!editable.hasClass('active')) {
-            editable.addClass('active').append(button);
-        }
-        if (editable.is('.annotation-inline-box')) {
-            $('*[x-annotation-box]', editable)
-                .css({position: 'absolute', left: event.clientX - editable.offset().left + 5, top: event.clientY - editable.offset().top + 5})
-                .show();
-        } else {
-            $('*[x-annotation-box]').hide();
-        }
-    });
-
-    $('.motyw').live('click', function() {
-        selectTheme($(this).attr('theme-class'));
-    });
-    
-    $('#insert-annotation-button').click(function() {
-        addAnnotation();
-        return false;
-    });
-    
-    $('#insert-theme-button').click(function() {
-        addTheme();
-        return false;
-    });
-}
-
-/*
- * History
- */
-
-function refreshHistory(callback){
-       $.blockUI({
-               message: 'Odświeżanie historii...'
-       });
-       
-       $.ajax({
-               url: document.location.href + '/history',
-        dataType: 'json',
-               error: function() {
-                       $('#history-view .message-box').html('Nie udało się odświeżyć historii').show();
-                       $.unblockUI();          
-               },
-               success: function(data) {
-                       $('#history-view .message-box').hide();
-                       var changes_list = $('#changes-list');
-                       changes_list.html('');
-                       
-                       $.each(data, function() {
-                               var val = this[0];
-                               changes_list.append('<tr>'
-                                       +'<td><input type="radio" name="rev_from" value="'+val+'">'
-                                               + '<input type="radio" name="rev_to" value="'+val+'">'
-                                       +'<td>'+ this[0]+'</td>'
-                                       +'<td>'+ this[3]+'</td>'
-                                       +'<td>'+ this[2]+'</td>'
-                                       +'<td>'+ this[1]+'</td></tr>')                  
-                       });                                                     
-                       $.unblockUI();  
-                       if(callback) callback();
-               }
-       });
-};
-
-function historyDiff(callback) {
-       var changelist = $('#changes-list');
-       var rev_a = $("input[name='rev_from']:checked", changelist);
-       var rev_b = $("input[name='rev_to']:checked", changelist);
-       
-       if (rev_a.length != 1 || rev_b.length != 1) {
-               window.alert("Musisz zaznaczyć dwie wersje do porównania.");
-               return false;
-       }
-       
-       if (rev_a.val() == rev_b.val()) {
-               window.alert("Musisz zaznaczyć dwie różne wersje do porównania.");
-               return false;
-       }
-                       
-       $.blockUI({
-               message: 'Wczytywanie porównania...'
-       });
-       
-       $.ajax({
-               url: document.location.href + '/diff/'+rev_a.val() + '/'+ rev_b.val(),
-        dataType: 'html',
-               error: function() {
-                       $.unblockUI();
-                       window.alert('Nie udało się wykonać porównania :(.')                                        
-               },
-               success: function(data) {
-                       $.unblockUI();                  
-                       var diffview = $('#diff-view');                 
-                       diffview.html(data);
-                       diffview.show();                                                        
-               }
-       });
-}
-       
-
-$(function() {
-    gallery('#sidebar', $('#document-meta .gallery').html());
-    html('#html-view');
-    
-    CodeMirror.fromTextArea('id_text', {
-        parserfile: 'parsexml.js',
-        path: STATIC_URL + "js/lib/codemirror/",
-        stylesheet: STATIC_URL + "css/xmlcolors_15032010.css",
-        parserConfig: {
-            useHTMLKludges: false
-        },
-        iframeClass: 'xml-iframe',             
-        textWrapping: true,
-               lineNumbers: true, 
-               width: "100%",
-        tabMode: 'spaces',
-        indentUnit: 0,
-        initCallback: function(editor) {
-            $('#save-button').click(function(event) {
-                event.preventDefault();
-                $.blockUI({message: $('#save-dialog')});
-            });
-            
-            $('#save-ok').click(function() {
-                $.blockUI({message: 'Zapisywanie...'});
-                
-                function doSave (argument) {
-                    var metaComment = '<!--';
-                    $('#document-meta div').each(function() {
-                        metaComment += '\n\t' + $(this).attr('class') + ': ' + $(this).html();
-                    });
-                    metaComment += '\n-->'
-
-                    var data = {
-                        name: $('#document-name').html(),
-                        text: metaComment + editor.getCode(),
-                        revision: $('#document-revision').html(),
-                        author: $('#username').html() || 'annonymous',
-                        comment: $('#komentarz').val()
-                    };
-
-                    $.ajax({
-                        url: document.location.href,
-                        type: "POST",
-                        dataType: "json",
-                        data: data,                
-                        success: function(data) {
-                            if (data.text) {
-                                editor.setCode(data.text);
-                                $('#document-revision').html(data.revision);
-                            } else {
-                                alert(data.errors);
-                            }
-                            $.unblockUI();
-                        },
-                        error: function(xhr, textStatus, errorThrown) {
-                            alert('error: ' + textStatus + ' ' + errorThrown);
-                        },
-                    })
-                }
-                
-                if ($('#simple-view-tab').hasClass('active')) {
-                    reverseTransform(editor, doSave);
-                } else {
-                    doSave();
-                }
-            });
-            
-            $('#save-cancel').click(function() {
-                $.unblockUI();
-            });
-                               
-            var tabs = $('ol#tabs li');
-                       
-                       tabs.click(function(event, callback) {
-                               tabs.removeClass('active');
-                               $('.editor').hide();
-                               $(this).addClass('active');
-                               $('#' + $(this).attr('ui:related')).show();                             
-                               $(this).trigger('wl:tabload', callback);                                                                
-                       });     
-                       
-                       
-            $('#simple-view-tab').bind('wl:tabload', function(event, callback) {
-                transform(editor, callback);
-            });
-                       
-                       $('#source-view-tab').bind('wl:tabload', function(event, callback) {
-                reverseTransform(editor, callback);
-            });                                        
-                       
-                       $('#history-view-tab').bind('wl:tabload', function(event, callback) {
-                               refreshHistory(callback);                                                               
-                       }); 
-                       
-                       $('#make-diff-button').click(historyDiff);
-
-            $('#source-editor .toolbar button').click(function(event) {
-                event.preventDefault();
-                var params = eval("(" + $(this).attr('ui:action-params') + ")");
-                scriptletCenter.scriptlets[$(this).attr('ui:action')](editor, params);
-            });                        
-
-            $('.toolbar select').change(function(event) {
-                var slug = $(this).val();
-
-                $('.toolbar-buttons-container').hide().filter('[data-group=' + slug + ']').show();
-                $(window).resize();
-            });
-
-            $('.toolbar-buttons-container').hide();
-            $('.toolbar select').change();
-
-                       
-                       $('#simple-view-tab').trigger('click', 
-                               function() { 
-                                       $('#loading-overlay').fadeOut();
-                                       return false; 
-                               });            
-        }
-    });
-    
-    $(window).resize(function() {
-        $('iframe').height($(window).height() - $('#tabs').outerHeight() - $('#source-editor .toolbar').outerHeight());
-    });
-    
-    $(window).resize();
-    
-    $('.vsplitbar').click(function() {
-        if ($('#sidebar').width() == 0) {
-            $('#sidebar').width(480).css({right: 0}).show();
-            $('#editor .editor').css({right: 495});
-            $('.vsplitbar').css({right: 480}).addClass('active');
-        } else {
-            $('#sidebar').width(0).hide();
-            $('#editor .editor').css({right: 15});
-            $('.vsplitbar').css({right: 0}).removeClass('active');
-        }
-        $(window).resize();
-    });
-       
-       $(window).bind('beforeunload', function(event) {
-               return "Na stronie mogą być niezapisane zmiany.";                                                             
-       });                
-
-});
diff --git a/platforma/static/js/wiki/base.js b/platforma/static/js/wiki/base.js
new file mode 100644 (file)
index 0000000..8c626d9
--- /dev/null
@@ -0,0 +1,58 @@
+(function($) 
+{      
+       $.wiki = {};
+       
+       $.wiki.Perspective = function(document, callback) {
+               // initialization
+       };
+       
+       $.wiki.Perspective.toString = function() {
+               return this.perspective_id;
+       }
+       
+       $.wiki.Perspective.prototype.onEnter = function () {
+               // called when perspective in initialized
+               document.location.hash = '#' + this.perspective_id; 
+               console.log(document.location.hash);
+       };
+       
+       $.wiki.Perspective.prototype.onExit = function () {
+               // called when user switches to another perspective 
+       };       
+       
+       $.wiki.Perspective.prototype.freezeState = function () {
+               // free UI state (don't store data here)
+       };
+       
+       $.wiki.Perspective.prototype.unfreezeState = function (frozenState) {
+               // restore UI state
+       };
+       
+       $.wiki.renderStub = function($container, $stub, data) 
+       {
+               var $elem = $stub.clone();
+               $elem.removeClass('row-stub');
+               $container.append($elem);
+       
+               $('*[data-stub-value]', $elem).each(function() {
+                       var $this = $(this);
+                       var field = $this.attr('data-stub-value');
+                       var value = data[field];
+               
+                       if(value === null || value === undefined) return;
+                        
+                       if(!$this.attr('data-stub-target')) {
+                               $this.text(value);                      
+                       }               
+                       else {
+                               $this.attr($this.attr('data-stub-target'), value);
+                               $this.removeAttr('data-stub-target');
+                               $this.removeAttr('data-stub-value');                    
+                       }               
+               });
+       
+               $elem.show();
+               return $elem;                                           
+       };
+               
+})(jQuery);
diff --git a/platforma/static/js/wiki/history.js b/platforma/static/js/wiki/history.js
new file mode 100644 (file)
index 0000000..87def8b
--- /dev/null
@@ -0,0 +1,92 @@
+(function($){
+
+    function fetchDiff(success, failed){
+        var changelist = $('#changes-list');
+        var rev_a = $("input[name='rev_from']:checked", changelist);
+        var rev_b = $("input[name='rev_to']:checked", changelist);
+        
+        if (rev_a.length != 1 || rev_b.length != 1) {
+            window.alert("Musisz zaznaczyć dwie wersje do porównania.");
+            failed();
+        }
+        
+        if (rev_a.val() == rev_b.val()) {
+            window.alert("Musisz zaznaczyć dwie różne wersje do porównania.");
+            failed();
+        }
+        
+        $.blockUI({
+            message: 'Wczytywanie porównania...'
+        });
+        
+        $.ajax({
+            url: document.location.href + '/diff/' + rev_a.val() + '/' + rev_b.val(),
+            dataType: 'html',
+            error: function(){
+                $.unblockUI();
+                error();
+            },
+            success: function(data){
+                var diffview = $('#diff-view');
+                diffview.html(data);
+                diffview.show();
+                $.unblockUI();
+                success();
+            }
+        });
+    }
+    
+    function HistoryPerspective(doc, callback) {
+               this.perspective_id = 'HistoryPerspective';
+               this.doc = doc;
+               
+        // first time page is rendered
+        $('#make-diff-button').click(fetchDiff);
+               callback.call(this);
+    };
+    
+    HistoryPerspective.prototype = new $.wiki.Perspective();
+    
+    HistoryPerspective.prototype.freezeState = function(){
+        // must 
+    };
+    
+    HistoryPerspective.prototype.onEnter = function(success, failure) 
+       {               
+               $.wiki.Perspective.prototype.onEnter.call(this);
+               
+        $.blockUI({
+            message: 'Odświeżanie historii...'
+        });
+               
+               function _finalize(s) {
+                       $.unblockUI();
+                       
+                       if(s) { if(success) success(); }
+                       else { if(failure) failure(); }
+               }
+        
+        function _failure(doc, message) {
+          $('#history-view .message-box').html('Nie udało się odświeżyć historii:' + message).show();
+                 _finalize(false);    
+        };
+          
+               function _success(doc, data) {
+               $('#history-view .message-box').hide();
+            var changes_list = $('#changes-list');
+            var $stub = $('#history-view .row-stub');                
+            changes_list.html('');
+                
+            $.each(data, function(){
+               $.wiki.renderStub(changes_list, $stub, this);
+            });
+                       
+                       _finalize(true);                        
+        };
+               
+               return this.doc.fetchHistory({success: _success, failure: _failure});
+    };    
+               
+       $.wiki.HistoryPerspective = HistoryPerspective;
+       
+})(jQuery);
diff --git a/platforma/static/js/wiki/main.js b/platforma/static/js/wiki/main.js
new file mode 100644 (file)
index 0000000..270bc7c
--- /dev/null
@@ -0,0 +1,361 @@
+
+if (!window.console) {
+    window.console = {
+        log: function(){
+        }
+    }
+}
+
+THEMES = ['Alkohol', 'Ambicja', 'Anioł', 'Antysemityzm', 'Arkadia', 'Artysta', 'Bezdomność', 'Bezpieczeństwo', 'Bieda', 'Bijatyka', 'Błazen', 'Błądzenie', 'Błoto', 'Bogactwo', 'Bóg', 'Brat', 'Bunt', 'Buntownik', 'Burza', 'Car', 'Carpe diem', 'Ciemność', 'Cień', 'Cisza', 'Chciwość', 'Chleb', 'Chłop', 'Choroba', 'Chrystus', 'Chrzest', 'Ciało', 'Cierpienie', 'Cmentarz', 'Cnota', 'Córka', 'Cud', 'Czarownika', 'Czary', 'Czas', 'Czyn', 'Czyściec', 'Dama', 'Danse macabre', 'Deszcz', 'Diabeł', 'Dobro', 'Dom', 'Dorosłość', 'Drzewo', 'Duch', 'Dusza', 'Duma', 'Dworek', 'Dworzanin', 'Dwór', 'Dzieciństwo', 'Dziecko', 'Dziedzictwo', 'Dziewictwo', 'Dźwięk', 'Egzorcyzm', 'Elita', 'Emigrant', 'Fałsz', 'Filozof', 'Fircyk', 'Flirt', 'Głupiec', 'Głupota', 'Głód', 'Gospodarz', 'Gospodyni', 'Gość', 'Gotycyzm', 'Góra', 'Gra', 'Grób', 'Grzech', 'Grzeczność', 'Gwiazda', 'Handel', 'Hańba', 'Historia', 'Honor', 'Idealista', 'Imię', 'Interes', 'Jabłka', 'Jedzenie', 'Jesień', 'Kaleka', 'Kara', 'Karczma', 'Klęska', 'Kłamstwo', 'Kłótnia', 'Kobieta', 'Kobieta demoniczna', 'Kobieta "upadła"', 'Kochanek', 'Kochanek romantyczny', 'Kolonializm', 'Kondycja ludzka', 'Konflikt', 'Konflikt wewnętrzny', 'Koniec świata', 'Koń', 'Korzyść', 'Kot', 'Kradzież', 'Krew', 'Król', 'Krzywda', 'Ksiądz', 'Książka', 'Księżyc', 'Kuchnia', 'Kuszenie', 'Kwiaty', 'Labirynt', 'Las', 'Lato', 'Lekarz', 'Lenistwo', 'List', 'Liberat', 'Los', 'Lud', 'Lustro', 'Łzy', 'Małżeństwo', 'Marzenie', 'Maska', 'Maszyna', 'Matka', 'Matka Boska', 'Mądrość', 'Mąż', 'Melancholia', 'Mędrzec', 'Mężczyzna', 'Miasto', 'Mieszczanin', 'Miłosierdzie', 'Miłość', 'Miłość niespełniona', 'Miłość platoniczna', 'Miłość romantyczna', 'Miłość silniejsza niż śmierć', 'Miłość spełniona', 'Miłość tragiczna', 'Mizoginia', 'Młodość', 'Moda', 'Modlitwa', 'Morderstwo', 'Morze', 'Motyl', 'Mucha', 'Muzyka', 'Narodziny', 'Naród', 'Natura', 'Nauczyciel', 'Nauczycielka', 'Nauka', 'Niebezpieczeństwo', 'Niedziela', 'Niemiec', 'Nienawiść', 'Nieśmiertelność', 'Niewola', 'Noc', 'Nuda', 'Obcy', 'Obłok', 'Obowiązek', 'Obraz świata', 'Obrzędy', 'Obyczaje', 'Obywatel', 'Odrodzenie przez grób', 'Odwaga', 'Ofiara', 'Ogień', 'Ogród', 'Ojciec', 'Ojczyzna', 'Oko', 'Okręt', 'Okrucieństwo', 'Omen', 'Opieka', 'Organizm', 'Otchłań', 'Pająk', 'Pamięć', 'Pan', 'Panna młoda', 'Państwo', 'Patriota', 'Piekło', 'Pielgrzym', 'Pieniądz', 'Pies', 'Piętno', 'Pijaństwo', 'Piwnica', 'Plotka', 'Pobożność', 'Pocałunek', 'Pochlebstwo', 'Poeta', 'Poetka', 'Poezja', 'Podróż', 'Podstęp', 'Pogrzeb', 'Pojedynek', 'Pokora', 'Pokusa', 'Polak', 'Polityka', 'Polowanie', 'Polska', 'Portret', 'Porwanie', 'Poświęcenie', 'Potwór', 'Powstanie', 'Powstaniec', 'Pozory', 'Pozycja społeczna', 'Pożar', 'Pożądanie', 'Praca', 'Praca u podstaw', 'Praca organiczna', 'Prawda', 'Prawnik', 'Prometeusz', 'Proroctwo', 'Prorok', 'Próżność', 'Przebranie', 'Przeczucie', 'Przedmurze chrześcijaństwa', 'Przekleństwo', 'Przekupstwo', 'Przemiana', 'Przemijanie', 'Przemoc', 'Przestrzeń', 'Przyjaźń', 'Przyroda nieożywiona', 'Przysięga', 'Przywódca', 'Ptak', 'Pustynia', 'Pycha', 'Raj', 'Realista', 'Religia', 'Rewolucja', 'Robak', 'Robotnik', 'Rodzina', 'Rosja', 'Rosjanin', 'Rośliny', 'Rozczarowanie', 'Rozpacz', 'Rozstanie', 'Rozum', 'Ruiny', 'Rycerz', 'Rzeka', 'Salon', 'Samobójstwo', 'Samolubstwo', 'Samotnik', 'Samotność', 'Sarmata', 'Sąsiad', 'Sąd', 'Sąd Ostateczny', 'Sen', 'Serce', 'Sędzia', 'Sielanka', 'Sierota', 'Siła', 'Siostra', 'Sława', 'Słońce', 'Słowo', 'Sługa', 'Służalczość', 'Skąpiec', 'Sobowtór', 'Społecznik', 'Spowiedź', 'Sprawiedliwość', 'Starość', 'Strach', 'Strój', 'Stworzenie', 'Sumienie', 'Swaty', 'Syberia', 'Syn', 'Syn marnotrawny', 'Syzyf', 'Szaleniec', 'Szaleństwo', 'Szantaż', 'Szatan', 'Szczęście', 'Szkoła', 'Szlachcic', 'Szpieg', 'Sztuka', 'Ślub', 'Śmiech', 'Śmierć', 'Śmierć bohaterska', 'Śpiew', 'Światło', 'Świętoszek', 'Święty', 'Świt', 'Tajemnica', 'Taniec', 'Tchórzostwo', 'Teatr', 'Testament', 'Tęsknota', 'Theatrum mundi', 'Tłum', 'Trucizna', 'Trup', 'Twórczość', 'Uczeń', 'Uczta', 'Uroda', 'Umiarkowanie', 'Upadek', 'Upiór', 'Urzędnik', 'Vanitas', 'Walka', 'Walka klas', 'Wampir', 'Warszawa', 'Wąż', 'Wdowa', 'Wdowiec', 'Wesele', 'Wiatr', 'Wierność', 'Wierzenia', 'Wieś', 'Wiedza', 'Wieża Babel', 'Więzienie', 'Więzień', 'Wina', 'Wino', 'Wiosna', 'Wizja', 'Władza', 'Własność', 'Woda', 'Wojna', 'Wojna pokoleń', 'Wolność', 'Wróg', 'Wspomnienia', 'Współpraca', 'Wygnanie', 'Wyrzuty sumienia', 'Wyspa', 'Wzrok', 'Zabawa', 'Zabobony', 'Zamek', 'Zaręczyny', 'Zaświaty', 'Zazdrość', 'Zbawienie', 'Zbrodnia', 'Zbrodniarz', 'Zdrada', 'Zdrowie', 'Zemsta', 'Zesłaniec', 'Ziarno', 'Ziemia', 'Zima', 'Zło', 'Złodziej', 'Złoty wiek', 'Zmartwychwstanie', 'Zwątpienie', 'Zwierzęta', 'Zwycięstwo', 'Żałoba', 'Żebrak', 'Żołnierz', 'Żona', 'Życie jako wędrówka', 'Życie snem', 'Żyd', 'Żywioły', 'Oświadczyny']
+
+function gallery(element, url){
+    var element = $(element);
+    var imageDimensions = {};
+    element.data('images', []);
+    
+    function changePage(pageNumber){
+        $('.gallery-image img', element).attr('src', element.data('images')[pageNumber - 1]);
+    }
+    
+    function normalizeNumber(pageNumber){
+        // Numer strony musi być pomiędzy 1 a najwyższym numerem
+        var pageCount = element.data('images').length;
+        pageNumber = parseInt(pageNumber, 10);
+        
+        if (!pageNumber || pageNumber == NaN || pageNumber == Infinity || pageNumber == -Infinity) {
+            return 1;
+        }
+        else 
+            if (pageNumber < 1) {
+                return 1;
+            }
+            else 
+                if (pageNumber > pageCount) {
+                    return pageCount;
+                }
+                else {
+                    return pageNumber;
+                }
+    }
+    
+    var pn = $('.page-number', element);
+    pn.change(function(event){
+        event.preventDefault();
+        var n = normalizeNumber(pn.val());
+        pn.val(n);
+        changePage(n);
+    });
+    $('.previous-page', element).click(function(){
+        pn.val(normalizeNumber(pn.val()) - 1);
+        pn.change();
+    });
+    $('.next-page', element).click(function(){
+        pn.val(normalizeNumber(pn.val()) + 1);
+        pn.change();
+    });
+    
+    
+    var image = $('.gallery-image img', element).attr('unselectable', 'on');
+    var origin = {};
+    var imageOrigin = {};
+    var zoomFactor = 1;
+    
+    $('.zoom-in', element).click(function(){
+        zoomFactor = Math.min(2, zoomFactor + 0.2);
+        zoom();
+    });
+    $('.zoom-out', element).click(function(){
+        zoomFactor = Math.max(0.2, zoomFactor - 0.2);
+        zoom();
+    });
+    $('.change-gallery', element).click(function(){
+        $('.chosen-gallery').val($('#document-meta .gallery').html() || '/platforma/gallery/');
+        $('.gallery-image').animate({
+            top: 60
+        }, 200);
+        $('.chosen-gallery').focus();
+    });
+    $('.change-gallery-ok', element).click(function(){
+        if ($('#document-meta .gallery').length == 0) {
+            $('<div class="gallery"></div>').appendTo('#document-meta');
+        }
+        $('#document-meta .gallery').html($('.chosen-gallery').val());
+        updateGallery($('.chosen-gallery').val());
+        $('.gallery-image').animate({
+            top: 30
+        }, 200);
+    });
+    $('.change-gallery-cancel', element).click(function(){
+        $('.gallery-image').animate({
+            top: 30
+        }, 200);
+    });
+    
+    $('.gallery-image img', element).load(function(){
+        image.css({
+            width: null,
+            height: null
+        });
+        imageDimensions = {
+            width: $(this).width() * zoomFactor,
+            height: $(this).height() * zoomFactor,
+            originWidth: $(this).width(),
+            originHeight: $(this).height(),
+            galleryWidth: $(this).parent().width(),
+            galleryHeight: $(this).parent().height()
+        };
+        
+        if (!(imageDimensions.width && imageDimensions.height)) {
+            setTimeout(function(){
+                $('.gallery-image img', element).load();
+            }, 100);
+        }
+        var position = normalizePosition(image.position().left, image.position().top, imageDimensions.galleryWidth, imageDimensions.galleryHeight, imageDimensions.width, imageDimensions.height);
+        image.css({
+            left: position.x,
+            top: position.y,
+            width: $(this).width() * zoomFactor,
+            height: $(this).height() * zoomFactor
+        });
+    });
+    
+    $(window).resize(function(){
+        imageDimensions.galleryWidth = image.parent().width();
+        imageDimensions.galleryHeight = image.parent().height();
+    });
+    
+    function bounds(galleryWidth, galleryHeight, imageWidth, imageHeight){
+        return {
+            maxX: 0,
+            maxY: 0,
+            minX: galleryWidth - imageWidth,
+            minY: galleryHeight - imageHeight
+        }
+    }
+    
+    function normalizePosition(x, y, galleryWidth, galleryHeight, imageWidth, imageHeight){
+        var b = bounds(galleryWidth, galleryHeight, imageWidth, imageHeight);
+        return {
+            x: Math.min(b.maxX, Math.max(b.minX, x)),
+            y: Math.min(b.maxY, Math.max(b.minY, y))
+        }
+    }
+    
+    function onMouseMove(event){
+        var position = normalizePosition(event.clientX - origin.x + imageOrigin.left, event.clientY - origin.y + imageOrigin.top, imageDimensions.galleryWidth, imageDimensions.galleryHeight, imageDimensions.width, imageDimensions.height);
+        image.css({
+            position: 'absolute',
+            top: position.y,
+            left: position.x
+        });
+        return false;
+    }
+    
+    function setZoom(factor){
+        zoomFactor = factor;
+    }
+    
+    function zoom(){
+        imageDimensions.width = imageDimensions.originWidth * zoomFactor;
+        imageDimensions.height = imageDimensions.originHeight * zoomFactor;
+        var position = normalizePosition(image.position().left, image.position().top, imageDimensions.galleryWidth, imageDimensions.galleryHeight, imageDimensions.width, imageDimensions.height);
+        image.css({
+            width: imageDimensions.width,
+            height: imageDimensions.height,
+            left: position.x,
+            top: position.y
+        });
+        
+    }
+    
+    function onMouseUp(event){
+        $(document).unbind('mousemove.gallery').unbind('mouseup.gallery');
+        return false;
+    }
+    
+    image.bind('mousedown', function(event){
+        origin = {
+            x: event.clientX,
+            y: event.clientY
+        };
+        imageOrigin = image.position();
+        $(document).bind('mousemove.gallery', onMouseMove).bind('mouseup.gallery', onMouseUp);
+        return false;
+    });
+    
+    function updateGallery(url){
+        $.ajax({
+            url: url,
+            type: 'GET',
+            dataType: 'json',
+            
+            success: function(data){
+                element.data('images', data);
+                pn.val(1);
+                pn.change();
+                $('.gallery-image img', element).show();
+            },
+            
+            error: function(data){
+                element.data('images', []);
+                pn.val(1);
+                pn.change();
+                $('.gallery-image img', element).hide();
+            }
+        });
+    }
+    
+    if (url) {
+        updateGallery(url);
+    }
+}
+
+$(function() {
+    // gallery('#sidebar', $('#document-meta .gallery').html());
+       
+       var tabs = $('ol#tabs li');             
+       var perspectives = {};
+       var wikidoc = new $.wikiapi.WikiDocument("document-meta");
+       
+       function activePerspective() {
+               return perspectives[$("#tabs " + document.location.hash + "-tab").attr('data-ui-jsclass')];             
+       };
+               
+    function initialize() 
+       {               
+               /* The save button */
+        $('#save-button').click(function(event){
+            event.preventDefault();
+            $.blockUI({
+                message: $('#save-dialog')
+            });
+        });
+        
+        $('#save-ok').click(function(){
+            $.blockUI({
+                message: 'Zapisywanie...'
+            });
+                       
+                       var ap = activePerspective();
+                       
+                       /* exit perspective */
+                       ap.onExit();          
+                       
+                       function finalize() {
+                               ap.onEnter();
+                               $.unblockUI();
+                       };
+                       
+                       wikidoc.save( $("#komentarz").text(), 
+                               function(doc, changed) {
+                                       console.log("Saved.");                          
+                                       finalize();                             
+                               }, 
+                               function(doc, message) {
+                                       alert(message);
+                                       finalize();                                     
+                               }
+                       );
+        });
+        
+        $('#save-cancel').click(function(){
+            $.unblockUI();
+        }); 
+                               
+               $('.editor').hide();   
+               
+               /*
+                * TABS 
+                */             
+        tabs.click(function(event, callback) {
+                       /* hide old */
+            var $old = tabs.filter('.active');
+                                               
+                       $old.each(function(){
+                               $(this).removeClass('active');
+                               $('#' + $(this).attr('data-ui-related')).hide();
+                               perspectives[$(this).attr('data-ui-jsclass')].onExit();
+                       });                     
+                       
+                       /* show new */                                          
+            $(this).addClass('active');
+            $('#' + $(this).attr('data-ui-related')).show();                   
+            perspectives[$(this).attr('data-ui-jsclass')].onEnter();
+        });
+                       
+        
+        $(window).resize(function(){
+            $('iframe').height($(window).height() - $('#tabs').outerHeight() - $('#source-editor .toolbar').outerHeight());
+        });
+        
+        $(window).resize();
+        
+        $('.vsplitbar').click(function(){
+            if ($('#sidebar').width() == 0) {
+                $('#sidebar').width(480).css({
+                    right: 0
+                }).show();
+                $('#editor .editor').css({
+                    right: 495
+                });
+                $('.vsplitbar').css({
+                    right: 480
+                }).addClass('active');
+            }
+            else {
+                $('#sidebar').width(0).hide();
+                $('#editor .editor').css({
+                    right: 15
+                });
+                $('.vsplitbar').css({
+                    right: 0
+                }).removeClass('active');
+            }
+            $(window).resize();
+        });
+        
+        $(window).bind('beforeunload', function(event){
+            return "Na stronie mogą być zmiany.";
+        });
+               
+               console.log("prepare for fetch");
+               
+               wikidoc.fetch({
+                       success: function(){
+                               console.log("Fetch success");
+                               $('#loading-overlay').fadeOut();                                
+                               var active_tab = document.location.hash || "#VisualPerspective";
+                               var $active = $("#tabs " + active_tab + "-tab");
+                               
+                               $active.trigger("click");
+                       },
+                       failure: function() {
+                               $('#loading-overlay').fadeOut();
+                               alert("FAILURE");
+                       }
+               });
+                                               
+    }; /* end of initialize() */
+       
+       var initAll = function(a, f) {                          
+               if (a.length == 0) return f();  
+                       
+               var klass = a.pop();
+               console.log("INIT", klass);             
+               var p = new $.wiki[klass](wikidoc, function() {
+                       perspectives[this.perspective_id] = this;                        
+                       initAll(a, f); 
+               });                                             
+               
+       };
+       
+       /*
+        * Initialize all perspectives 
+        */
+       initAll($.makeArray( $('ol#tabs li').map(function(){
+                       return $(this).attr('data-ui-jsclass');                                         
+       })), initialize);
+       
+       console.log(location.hash);
+       
+});
diff --git a/platforma/static/js/wiki/source_editor.js b/platforma/static/js/wiki/source_editor.js
new file mode 100644 (file)
index 0000000..6f7ed3d
--- /dev/null
@@ -0,0 +1,64 @@
+/* COMMENT */
+(function($) {
+       
+       function CodeMirrorPerspective(doc, callback) 
+       {
+               this.perspective_id = 'CodeMirrorPerspective';
+               this.doc = doc;
+               
+               var self = this;
+               
+               $('#source-editor .toolbar button').click(function(event){
+            event.preventDefault();
+            var params = eval("(" + $(this).attr('ui:action-params') + ")");
+            scriptletCenter.scriptlets[$(this).attr('ui:action')](editor, params);
+        });
+        
+        $('.toolbar select').change(function(event){
+            var slug = $(this).val();
+            
+            $('.toolbar-buttons-container').hide().filter('[data-group=' + slug + ']').show();
+            $(window).resize();
+        });
+        
+        $('.toolbar-buttons-container').hide();
+        $('.toolbar select').change();
+               
+               this.codemirror = CodeMirror.fromTextArea('codemirror_placeholder', {                   
+                       parserfile: 'parsexml.js',
+                       path: STATIC_URL + "js/lib/codemirror/",
+                       stylesheet: STATIC_URL + "css/xmlcolors_15032010.css",
+                       parserConfig: {
+                               useHTMLKludges: false
+                       },
+                       iframeClass: 'xml-iframe',
+                       textWrapping: true,
+                       lineNumbers: true,
+                       width: "100%",
+                       tabMode: 'spaces',
+                       indentUnit: 0,
+                       initCallback: function() {
+                               console.log("Initialized CodeMirror");
+                               callback.call(self);
+                       }       
+               });
+       };
+       
+       
+       CodeMirrorPerspective.prototype = new $.wiki.Perspective();
+       
+       CodeMirrorPerspective.prototype.freezeState = function() {
+               
+       };
+       
+       CodeMirrorPerspective.prototype.onEnter = function(success, failure) {
+               $.wiki.Perspective.prototype.onEnter.call(this);
+       
+               console.log(this.doc);
+               this.codemirror.setCode(this.doc.text);
+               if(success) success();
+       }
+       
+       $.wiki.CodeMirrorPerspective = CodeMirrorPerspective;
+               
+})(jQuery);
diff --git a/platforma/static/js/wiki/wikiapi.js b/platforma/static/js/wiki/wikiapi.js
new file mode 100644 (file)
index 0000000..d151f9e
--- /dev/null
@@ -0,0 +1,211 @@
+(function($) {
+       
+       $.wikiapi = {};
+       
+       var noop = function() {};
+       var noops = {'success': noop, 'failure': noop};
+       
+       /*
+        * Return absolute reverse path of given named view.
+        * (at least he have it hard-coded in one place)
+        * 
+        * TODO: think of a way, not to hard-code it here ;) 
+        * 
+        */
+       function reverse() {
+               var vname = arguments[0];
+                       
+               if(vname == "ajax_document_text") {
+                       var path = "/" + arguments[1] + "/text";
+                       if (arguments[2] !== undefined) 
+                               path += "/" + arguments[2];
+                       return path;
+               }
+                       
+               if (vname == "ajax_document_history") {
+                       return "/" + arguments[1] + "/history";
+               }                       
+                                       
+               if(vname == "ajax_document_diff")
+                       return "/" + arguments[1] + "/diff/" + arguments[2] + "/" + arguments[3] 
+                       
+               console.log("Couldn't reverse match:", vname);
+               return "/404.html";             
+       };
+       
+       /*
+        * Document Abstraction  
+        */
+       function WikiDocument(element_id) {
+               var meta = $('#'+element_id);
+               
+               this.id = meta.attr('data-document-name');              
+               this.revision = $("*[data-key='revision']", meta).text();
+               this.gallery = $("*[data-key='gallery']", meta).text();
+               
+               this.text = null;
+               
+               this.has_local_changes = false;
+               this._lock = -1;
+               this._context_lock = -1;
+               this._lock_count = 0; 
+       }
+       
+//     WikiDocument.prototype.lock = function() {
+//             if(this._lock < 0) {
+//                     this._lock = Math.random();
+//                     this._context_lock = this._lock;
+//                     this._lock_count = 1;
+//                     return this._lock;
+//             }
+//             
+//             // reentrant locks 
+//             if(this._context_lock === this._lock) {
+//                     this._lock_count += 1;
+//                     return this._lock;
+//             }
+//             
+//             throw "Document operation in progress. Try again later."
+//     };
+//             
+//     WikiDocument.prototype.unlock = function(lockNumber) {
+//             if(this.locked === lockNumber) {
+//                     this._lock_count -= 1;
+//                     
+//                     if(this._lock_count === 0) {
+//                             this._lock = -1;
+//                             this._context_lock = -1;
+//                     };                      
+//                     return;
+//             }
+//             throw "Trying to unlock with wrong lockNumber";
+//     };
+//     
+//     /*
+//      * About to leave context of current lock.
+//      */
+//     WikiDocument.prototype.leaveContext = function() {
+//             var old = this._context_lock;
+//             this._context_lock = -1;
+//             return old;
+//     };
+       
+       /*
+        * Fetch text of this document.
+        */
+       WikiDocument.prototype.fetch = function(params) {               
+               params = $.extend({}, noops, params);
+               var self = this;
+               
+               $.ajax({
+                       method: "GET",
+                       url: reverse("ajax_document_text", self.id),
+                       dataType: 'json', 
+                       success: function(data) 
+                       {
+                               var changed = false;
+                               
+                               if (self.text === null || self.revision !== data.revision) {
+                                       self.text = data.text;
+                                       self.revision = data.revision;
+                                       self.gallery = data.gallery;                                    
+                                       changed = true;
+                               }
+                               
+                               self.has_local_changes = false;                         
+                               params['success'](self, changed);
+                       },
+                       error: function() {             
+                               params['failure'](self, "Nie udało się wczytać treści dokumentu.");
+                       }
+               });                                             
+       };
+       
+       /*
+        * Fetch history of this document.
+        * 
+        * from - First revision to fetch (default = 0)
+        * upto - Last revision to fetch (default = tip)
+        * 
+        */
+       WikiDocument.prototype.fetchHistory = function(params) {                
+               /* this doesn't modify anything, so no locks */         
+               params = $.extend({}, noops, params);           
+               var self = this;
+               
+               $.ajax({                        
+                       method: "GET",
+                       url: reverse("ajax_document_history", self.id),
+                       dataType: 'json',
+                       data: {"from": params['from'], "upto": params['upto']},
+                       success: function(data) {
+                               params['success'](self, data);
+                       },
+                       error: function() {
+                               params['failure'](self, "Nie udało się wczytać treści dokumentu.");
+                       }
+               });                                             
+       };
+       
+       /*
+        * Set document's text
+        */
+       WikiDocument.prototype.setText = function(text) {                               
+               this.text = text;
+               this.has_local_changes = true;                  
+       };
+       
+       /*
+        * Set document's gallery link
+        */
+       WikiDocument.prototype.setGallery = function(gallery) {                         
+               this.gallery = gallery;
+               this.has_local_changes = true;                  
+       };
+       
+       /*
+        * Save text back to the server
+        */
+       WikiDocument.prototype.save = function(comment, success, failure){
+               var self = this;
+               
+               if (!self.has_local_changes) {
+                       return success(self, "Nie ma zmian do zapisania.");
+               }
+               
+               /* you can't set text while some is fetching it (or saving) */
+               var metaComment = '<!--';
+               metaComment += '\n\tgallery:' + self.gallery;
+               metaComment += '\n-->'
+               
+               var data = {
+                       name: self.id,
+                       text: self.text,
+                       parent_revision: self.revision,
+                       comment: comment,
+               };
+               
+               $.ajax({
+                       url: reverse("ajax_document_text", self.id),
+                       type: "POST",
+                       dataType: "json",
+                       data: data,
+                       success: function(data){
+                               var changed = false;
+                               if (data.text) {
+                                       self.text = data.text;
+                                       self.revision = data.revision;
+                                       self.gallery = data.gallery;
+                                       changed = true;
+                               }
+                               success(self, changed);
+                       },
+                       error: function(){
+                               failure(self, "Nie udało się zapisać.");
+                       }
+               });             
+       }; /* end of save() */
+       
+       $.wikiapi.WikiDocument = WikiDocument;
+       
+})(jQuery);
diff --git a/platforma/static/js/wiki/wysiwyg_editor.js b/platforma/static/js/wiki/wysiwyg_editor.js
new file mode 100644 (file)
index 0000000..4a84e9d
--- /dev/null
@@ -0,0 +1,416 @@
+(function($){
+
+    /* Show theme to the user */
+    function selectTheme(themeId){
+        var selection = window.getSelection();
+        selection.removeAllRanges();
+        
+        var range = document.createRange();
+        var s = $(".motyw[theme-class='" + themeId + "']")[0];
+        var e = $(".end[theme-class='" + themeId + "']")[0];
+        
+        if (s && e) {
+            range.setStartAfter(s);
+            range.setEndBefore(e);
+            selection.addRange(range);
+        }
+    };
+    
+    /* Verify insertion port for annotation or theme */
+    function verifyTagInsertPoint(node){
+        if (node.nodeType == 3) { // Text Node
+            node = node.parentNode;
+        }
+        
+        if (node.nodeType != 1) {
+            return false;
+        }
+        
+        node = $(node);
+        var xtype = node.attr('x-node');
+        
+        if (!xtype || (xtype.search(':') >= 0) ||
+        xtype == 'motyw' ||
+        xtype == 'begin' ||
+        xtype == 'end') {
+            return false;
+        }
+        
+        // don't allow themes inside annotations
+        if (node.is('*[x-annotation-box] *')) 
+            return false;
+        
+        return true;
+    }
+    
+    /* Convert HTML frament to plaintext */
+    var ANNOT_ALLOWED = ['wyroznienie', 'slowo_obce', 'osoba'];
+    
+    function html2plainText(fragment){
+        var text = "";
+        
+        $(fragment.childNodes).each(function(){
+            if (this.nodeType == 3) // textNode
+                text += this.nodeValue;
+            else 
+                if (this.nodeType == 1 &&
+                $.inArray($(this).attr('x-node'), ANNOT_ALLOWED) != -1) {
+                    text += html2plainText(this);
+                }
+        });
+        
+        return text;
+    }
+    
+    
+    /* Insert annotation using current selection */
+    function addAnnotation(){
+        var selection = window.getSelection();
+        var n = selection.rangeCount;
+        
+        if (n == 0) {
+            window.alert("Nie zaznaczono żadnego obszaru");
+            return false;
+        }
+        
+        // for now allow only 1 range
+        if (n > 1) {
+            window.alert("Zaznacz jeden obszar");
+            return false;
+        }
+        
+        // remember the selected range
+        var range = selection.getRangeAt(0);
+        
+        if (!verifyTagInsertPoint(range.endContainer)) {
+            window.alert("Nie można wstawić w to miejsce przypisu.");
+            return false;
+        }
+        
+        // BUG #273 - selected text can contain themes, which should be omited from
+        // defining term
+        var text = html2plainText(range.cloneContents());
+        
+        var tag = $('<span></span>');
+        range.collapse(false);
+        range.insertNode(tag[0]);
+        
+        xml2html({
+            xml: '<pr><slowo_obce>' + text + '</slowo_obce> --- </pr>',
+            success: function(text){
+                var t = $(text);
+                tag.replaceWith(t);
+                openForEdit(t);
+            },
+            error: function(){
+                tag.remove();
+                alert('Błąd przy dodawaniu przypisu:' + errors);
+            }
+        })
+    }
+    
+    
+    /* Insert theme using current selection */
+    
+    function addTheme(){
+        var selection = window.getSelection();
+        var n = selection.rangeCount;
+        
+        if (n == 0) {
+            window.alert("Nie zaznaczono żadnego obszaru");
+            return false;
+        }
+        
+        // for now allow only 1 range
+        if (n > 1) {
+            window.alert("Zaznacz jeden obszar.");
+            return false;
+        }
+        
+        
+        // remember the selected range
+        var range = selection.getRangeAt(0);
+        
+        
+        if ($(range.startContainer).is('.html-editarea') ||
+        $(range.endContainer).is('.html-editarea')) {
+            window.alert("Motywy można oznaczać tylko na tekście nie otwartym do edycji. \n Zamknij edytowany fragment i spróbuj ponownie.");
+            return false;
+        }
+        
+        // verify if the start/end points make even sense -
+        // they must be inside a x-node (otherwise they will be discarded)
+        // and the x-node must be a main text
+        if (!verifyTagInsertPoint(range.startContainer)) {
+            window.alert("Motyw nie może się zaczynać w tym miejscu.");
+            return false;
+        }
+        
+        if (!verifyTagInsertPoint(range.endContainer)) {
+            window.alert("Motyw nie może się kończyć w tym miejscu.");
+            return false;
+        }
+        
+        var date = (new Date()).getTime();
+        var random = Math.floor(4000000000 * Math.random());
+        var id = ('' + date) + '-' + ('' + random);
+        
+        var spoint = document.createRange();
+        var epoint = document.createRange();
+        
+        spoint.setStart(range.startContainer, range.startOffset);
+        epoint.setStart(range.endContainer, range.endOffset);
+        
+        var mtag, btag, etag, errors;
+        
+        // insert theme-ref
+        
+        xml2html({
+            xml: '<end id="e' + id + '" />',
+            success: function(text){
+                etag = $('<span></span>');
+                epoint.insertNode(etag[0]);
+                etag.replaceWith(text);
+                xml2html({
+                    xml: '<motyw id="m' + id + '"></motyw>',
+                    success: function(text){
+                        mtag = $('<span></span>');
+                        spoint.insertNode(mtag[0]);
+                        mtag.replaceWith(text);
+                        xml2html({
+                            xml: '<begin id="b' + id + '" />',
+                            success: function(text){
+                                btag = $('<span></span>');
+                                spoint.insertNode(btag[0])
+                                btag.replaceWith(text);
+                                selection.removeAllRanges();
+                                openForEdit($('.motyw[theme-class=' + id + ']'));
+                            }
+                        });
+                    }
+                });
+            }
+        });
+    }
+    
+    /* open edition window for selected fragment */
+    function openForEdit($origin){
+        var $box = null
+        
+        // annotations overlay their sub box - not their own box //
+        if ($origin.is(".annotation-inline-box")) {
+            $box = $("*[x-annotation-box]", $origin);
+        }
+        else {
+            $box = $origin;
+        }
+        
+        var x = $box[0].offsetLeft;
+        var y = $box[0].offsetTop;
+        var w = $box.outerWidth();
+        var h = $box.innerHeight();
+        
+        if ($origin.is(".annotation-inline-box")) {
+            w = Math.max(w, 400);
+            h = Math.max(h, 60);
+        }
+        
+        // start edition on this node
+        var $overlay = $('<div class="html-editarea"><button class="accept-button">Zapisz</button><button class="delete-button">Usuń</button><textarea></textarea></div>').css({
+            position: 'absolute',
+            height: h,
+            left: x,
+            top: y,
+            width: w
+        }).appendTo($box[0].offsetParent || $box.parent()).show();
+        
+        if ($origin.is('.motyw')) {
+            $('textarea', $overlay).autocomplete(THEMES, {
+                autoFill: true,
+                multiple: true,
+                selectFirst: true
+            });
+        }
+        
+        $('.delete-button', $overlay).click(function(){
+            if ($origin.is('.motyw')) {
+                $('[theme-class=' + $origin.attr('theme-class') + ']').remove();
+            }
+            else {
+                $origin.remove();
+            }
+            $overlay.remove();
+            $(document).unbind('click.blur-overlay');
+            return false;
+        })
+        
+        
+        var serializer = new XMLSerializer();
+        
+        html2text({
+            element: $box[0],
+            stripOuter: true,
+            success: function(text){
+                $('textarea', $overlay).val($.trim(text));
+                
+                setTimeout(function(){
+                    $('textarea', $overlay).elastic().focus();
+                }, 50);
+                
+                function save(argument){
+                    var nodeName = $box.attr('x-node') || 'pe';
+                    var insertedText = $('textarea', $overlay).val();
+                    
+                    if ($origin.is('.motyw')) {
+                        insertedText = insertedText.replace(/,\s*$/, '');
+                    }
+                    
+                    xml2html({
+                        xml: '<' + nodeName + '>' + insertedText + '</' + nodeName + '>',
+                        success: function(element){
+                            $origin.html($(element).html());
+                            $overlay.remove();
+                        },
+                        error: function(text){
+                            $overlay.remove();
+                            alert('Błąd! ' + text);
+                        }
+                    })
+                }
+                
+                $('.accept-button', $overlay).click(function(){
+                    save();
+                });
+                
+                $(document).bind('click.blur-overlay', function(event){
+                    if ($(event.target).parents('.html-editarea').length > 0) {
+                        return;
+                    }
+                    save();
+                    
+                    $(document).unbind('click.blur-overlay');
+                });
+                
+            },
+            error: function(text){
+                alert('Błąd! ' + text);
+            }
+        });
+    }
+           
+    function VisualPerspective(doc, callback) 
+       {
+               this.perspective_id = 'VisualPerspective';
+               this.doc = doc;
+               
+               var element = $("html-view");           
+               var button = $('<button class="edit-button">Edytuj</button>');
+               
+        $('#html-view').bind('mousemove', function(event){
+            var editable = $(event.target).closest('*[x-editable]');
+            $('.active[x-editable]', element).not(editable).removeClass('active').children('.edit-button').remove();
+            if (!editable.hasClass('active')) {
+                editable.addClass('active').append(button);
+            }
+            if (editable.is('.annotation-inline-box')) {
+                $('*[x-annotation-box]', editable).css({
+                    position: 'absolute',
+                    left: event.clientX - editable.offset().left + 5,
+                    top: event.clientY - editable.offset().top + 5
+                }).show();
+            }
+            else {
+                $('*[x-annotation-box]').hide();
+            }
+        });
+        
+        $('.motyw').live('click', function(){
+            selectTheme($(this).attr('theme-class'));
+        });
+        
+        $('#insert-annotation-button').click(function(){
+            addAnnotation();
+            return false;
+        });
+        
+        $('#insert-theme-button').click(function(){
+            addTheme();
+            return false;
+        });
+        
+        $('.edit-button').live('click', function(event){
+            event.preventDefault();
+            openForEdit($(this).parent());
+        });
+               
+               callback.call(this);
+    };
+    
+    VisualPerspective.prototype = new $.wiki.Perspective();
+       
+    VisualPerspective.prototype.freezeState = function() {
+    
+    };
+       
+       VisualPerspective.prototype.onEnter = function(success, failure) 
+       {
+               $.wiki.Perspective.prototype.onEnter.call(this);
+               
+        $.blockUI({
+            message: 'Uaktualnianie widoku...'
+        });
+               
+               function _finalize(callback) {
+                       $.unblockUI();
+                       if (callback) callback();                
+               } 
+               
+        xml2html({
+            xml: this.doc.text,
+            success: function(element){
+                $('#html-view').html(element);
+                _finalize(success);
+            },
+            error: function(text) {
+                var message = $('<pre></pre>');
+                message.text(text);
+                $('#html-view').html('<p class="error">Wystąpił błąd:</p><pre>' +
+                message.html() +
+                '</pre>');                                                             
+                               _finalize(failure);
+            }
+        });   
+       };
+       
+       VisualPerspective.prototype.onExit = function(success, failure) 
+       {
+               var self = this;
+               
+        $.blockUI({
+            message: 'Zapisywanie widoku...'
+        });    
+               
+               function _finalize(callback) {
+                       $.unblockUI();
+                       if (callback) callback();                
+               }
+               
+               if ($('#html-view .error').length > 0) 
+                       return _finalize(failure);        
+               
+        html2text({
+            element: $('#html-view div').get(0),
+            success: function(text) {
+                self.doc.setText(text);
+                _finalize(success);
+            },
+            error: function(text) {                
+                $('#source-editor').html('<p>Wystąpił błąd:</p><pre>' + text + '</pre>');                                          
+                               _finalize(failure);
+            }
+        });   
+       };
+       
+       $.wiki.VisualPerspective = VisualPerspective;    
+    
+})(jQuery);
diff --git a/platforma/static/js/wiki/xslt.js b/platforma/static/js/wiki/xslt.js
new file mode 100644 (file)
index 0000000..566b0a8
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * 
+ * XSLT STUFF
+ * 
+ */
+function createXSLT(xsl) {
+    var p = new XSLTProcessor();
+    p.importStylesheet(xsl);
+    return p;
+}
+
+var xml2htmlStylesheet = null;
+
+// Wykonuje block z załadowanymi arkuszami stylów
+function withStylesheets(code_block, onError) 
+{      
+    if (!xml2htmlStylesheet) {
+       $.blockUI({message: 'Ładowanie arkuszy stylów...'});
+       $.ajax({
+               url: STATIC_URL + 'xsl/wl2html_client.xsl',
+               dataType: 'xml',
+               success: function(data) {
+               xml2htmlStylesheet = createXSLT(data);
+                $.unblockUI();
+                               code_block();
+                 
+            },
+                       error: onError
+        })
+    }
+       else {
+               code_block();
+       }
+}
+
+
+function xml2html(options) {
+    withStylesheets(function() {
+        var xml = options.xml.replace(/\/\s+/g, '<br />');                             
+        var parser = new DOMParser();
+        var serializer = new XMLSerializer();
+        var doc = parser.parseFromString(xml, 'text/xml');             
+        var error = $('parsererror', doc);
+        
+        if (error.length == 0) {
+            doc = xml2htmlStylesheet.transformToFragment(doc, document);
+                       console.log(doc.firstChild);
+                       
+                       if(doc.firstChild === null) {
+                               options.error("Błąd w przetwarzaniu XML.");
+                               return;
+                       }
+                               
+            error = $('parsererror', doc);
+        }
+        
+        if (error.length > 0 && options.error) {
+            options.error(error.text());
+        } else {                       
+            options.success(doc.firstChild);
+        }
+    }, function() { options.error && options.error('Nie udało się załadować XSLT'); });
+}
+
+/* USEFULL CONSTANTS */
+const ELEMENT_NODE                                      = 1;
+const ATTRIBUTE_NODE                 = 2;
+const TEXT_NODE                      = 3;
+const CDATA_SECTION_NODE             = 4;
+const ENTITY_REFERENCE_NODE          = 5;
+const ENTITY_NODE                    = 6;
+const PROCESSING_INSTRUCTION_NODE    = 7;
+const COMMENT_NODE                   = 8;
+const DOCUMENT_NODE                  = 9;
+const DOCUMENT_TYPE_NODE             = 10;
+const DOCUMENT_FRAGMENT_NODE         = 11;
+const NOTATION_NODE                  = 12;
+const XATTR_RE = /^x-attr-name-(.*)$/;
+
+const ELEM_START = 1;
+const ELEM_END = 2;
+const NS_END = 3;
+
+const NAMESPACES = {
+       // namespaces not listed here will be assigned random names
+       "http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf",
+       "http://purl.org/dc/elements/1.1/": "dc",
+       "http://www.w3.org/XML/1998/namespace": "xml"
+};
+
+/*
+ * PADDING for pretty-printing
+ */
+const PADDING = {
+    dramat_wierszowany_l: 4,
+    dramat_wierszowany_lp: 4,
+    dramat_wspolczesny: 4,
+    wywiad: 4,
+    opowiadanie: 4,
+    powiesc: 4,
+    liryka_l: 4,
+    liryka_lp: 4,
+    naglowek_czesc: 4,
+    naglowek_akt: 4,
+    naglowek_rozdzial: 4,
+    naglowek_osoba: 4,
+    lista_osob: 4,
+    
+    akap: 3,
+    akap_cd: 3,
+    akap_dialog: 3,
+    strofa: 3,
+    motto: 3, 
+    miejsce_czas: 3,
+        
+    autor_utworu: 2,
+    nazwa_utworu: 2,
+    dzielo_nadrzedne: 2,
+       
+    didaskalia: 2,
+    motto_podpis: 2,
+    naglowek_listy: 2,
+    kwestia: 1,
+    lista_osoba: 1,
+       
+       "podpis": 1,    
+       "wers": 0,
+       "wers_cd": 0,
+       "wers_akap": 0,
+       "wers_wciety": 0,       
+       
+       "rdf:RDF": 3,
+       "rdf:Description": 1,   
+};
+
+function getPadding(name) {
+       
+       if(name.match(/^dc:.*$/))
+               return -1;
+       
+       if(PADDING[name])
+               return PADDING[name];
+               
+       return 0;
+}
+
+function HTMLSerializer() {    
+       // empty constructor
+}
+
+
+
+HTMLSerializer.prototype._prepare = function() {
+       this.stack = [];
+       
+       // XML namespace is implicit
+       this.nsMap = {"http://www.w3.org/XML/1998/namespace": "xml"};
+               
+       this.result = "";
+       this.nsCounter = 1;     
+}
+
+HTMLSerializer.prototype._pushElement = function(element) {
+       this.stack.push({
+               "type": ELEM_START,
+               "node": element
+       });     
+}
+
+HTMLSerializer.prototype._pushChildren = function(element) {
+       for(var i = element.childNodes.length-1; i >= 0; i--)
+               this._pushElement(element.childNodes.item(i));                                  
+}
+
+HTMLSerializer.prototype._pushTagEnd = function(tagName) {
+       this.stack.push({
+               "type": ELEM_END,
+               "tagName": tagName
+       });     
+}
+
+HTMLSerializer.prototype._verseBefore = function(node) {
+       var prev = node.previousSibling;
+       
+       while((prev !== null) && (prev.nodeType != ELEMENT_NODE)) {
+               prev = prev.previousSibling;
+       }       
+               
+       return (prev !== null) && prev.hasAttribute('x-verse');
+}
+
+HTMLSerializer.prototype.serialize = function(rootElement, stripOuter) 
+{
+       var self = this;
+       self._prepare();
+       
+       if(!stripOuter)
+               self._pushElement(rootElement);
+       else    
+               self._pushChildren(rootElement);
+       
+       while(self.stack.length > 0) {
+               var token = self.stack.pop();
+                                               
+               if(token.type === ELEM_END) {
+                       self.result += "</" + token.tagName + ">";                                      
+                       for(var padding = getPadding(token.tagName); padding > 0; padding--) {                  
+                               self.result += "\n";                    
+                       }
+                       continue;
+               };
+               
+               if(token.type === NS_END) {
+                       self._unassignNamespace(token.namespace);
+                       continue;
+               } 
+               
+               
+               switch(token.node.nodeType) {
+                       case ELEMENT_NODE:
+                               if(token.node.hasAttribute('x-pass-thru')) {
+                                       self._pushChildren(token.node);
+                                       break;
+                               }
+                               
+                               if(!token.node.hasAttribute('x-node'))
+                                       break;
+                                       
+                               var xnode = token.node.getAttribute('x-node');
+                               
+                               if(xnode === 'wers') {
+                                       /* push children */
+                                       if(self._verseBefore(token.node))
+                                               self.result += '/\n';
+                                       self._pushChildren(token.node);
+                                       break;                                  
+                               };                                      
+                               
+                               if(xnode === 'out-of-flow-text') {
+                                       self._pushChildren(token.node);
+                                       break;                                                                          
+                               }
+                               
+                               if(token.node.hasAttribute('x-verse') && self._verseBefore(token.node)) {
+                                       self.result += '/\n';                                   
+                               };
+                                       
+                               self._serializeElement(token.node);
+                               break;
+                       case TEXT_NODE:
+                               self.result += token.node.nodeValue;
+                               break;
+               };
+       };
+       
+       return this.result;
+}
+
+/*
+ * TODO: this doesn't support prefix redefinitions
+ */
+HTMLSerializer.prototype._unassignNamespace = function(nsData) {
+       this.nsMap[nsData.uri] = undefined;
+};
+       
+HTMLSerializer.prototype._assignNamespace = function(uri) {
+       if(uri === null) {
+               // default namespace
+               return ({"prefix": "", "uri": "", "fresh": false});
+       }
+       
+       if(this.nsMap[uri] === undefined) {
+               // this prefix hasn't been defined yet in current context       
+               var prefix = NAMESPACES[uri];
+               
+               if (prefix === undefined) { // not predefined
+                       prefix = "ns" + this.nsCounter;
+                       this.nsCounter += 1;
+               }
+               
+               this.nsMap[uri] = prefix;               
+               return ({
+                       "prefix": prefix,
+                       "uri": uri,
+                       "fresh": true
+               });                     
+       }       
+               
+       return ({"prefix": this.nsMap[uri], "uri": uri, "fresh": false});               
+};
+
+HTMLSerializer.prototype._join = function(prefix, name) {
+       if(!!prefix) 
+               return prefix + ":" + name;
+       return name;    
+};
+
+HTMLSerializer.prototype._rjoin = function(prefix, name) {
+       if(!!name) 
+               return prefix + ":" + name;
+       return prefix;  
+};
+                                       
+HTMLSerializer.prototype._serializeElement = function(node) {
+       var self = this;
+               
+       var ns = node.getAttribute('x-ns');
+       var nsPrefix = null;
+       var newNamespaces = [];
+       
+       var nsData = self._assignNamespace(node.getAttribute('x-ns'));
+       
+       if(nsData.fresh) {
+               newNamespaces.push(nsData);
+               self.stack.push({
+                       "type": NS_END,
+                       "namespace": nsData
+               });
+       }                                       
+       
+       var tagName = self._join(nsData.prefix, node.getAttribute('x-node'));
+                               
+       /* retrieve attributes */
+       var attributeIDs = [];
+       for (var i = 0; i < node.attributes.length; i++) {
+               var attr = node.attributes.item(i);
+               
+               // check if name starts with "x-attr-name"
+               var m = attr.name.match(XATTR_RE);
+               if (m !== null) 
+                       attributeIDs.push(m[1]);                                
+       };
+                               
+       /* print out */
+       if (getPadding(tagName))
+               self.result += '\n';
+               
+       self.result += '<' + tagName;   
+                                       
+       $.each(attributeIDs, function() {
+               var nsData = self._assignNamespace(node.getAttribute('x-attr-ns-'+this));
+       
+               if(nsData.fresh) {
+                       newNamespaces.push(nsData);
+                       self.stack.push({
+                               "type": NS_END,
+                               "namespace": nsData
+                       });
+               };
+                                                                                                                       
+               self.result += ' ' + self._join(nsData.prefix, node.getAttribute('x-attr-name-'+this));
+               self.result += '="'+node.getAttribute('x-attr-value-'+this) +'"';
+       });
+       
+       /* print new namespace declarations */
+       $.each(newNamespaces, function() {
+               self.result += " " + self._rjoin("xmlns", this.prefix);
+               self.result += '="' + this.uri + '"';           
+       });                                     
+       
+       if (node.childNodes.length > 0) {
+               self.result += ">";
+               self._pushTagEnd(tagName);
+               self._pushChildren(node);
+       }
+       else {
+               self.result += "/>";
+       };
+};
+
+function html2text(params) {   
+       try {
+               var s = new HTMLSerializer();
+               params.success( s.serialize(params.element, params.stripOuter) );
+       } catch(e) {
+               params.error("Nie udało się zserializować tekstu:" + e)
+       }       
+}
\ No newline at end of file
diff --git a/platforma/static/js/xslt.js b/platforma/static/js/xslt.js
deleted file mode 100644 (file)
index 566b0a8..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * 
- * XSLT STUFF
- * 
- */
-function createXSLT(xsl) {
-    var p = new XSLTProcessor();
-    p.importStylesheet(xsl);
-    return p;
-}
-
-var xml2htmlStylesheet = null;
-
-// Wykonuje block z załadowanymi arkuszami stylów
-function withStylesheets(code_block, onError) 
-{      
-    if (!xml2htmlStylesheet) {
-       $.blockUI({message: 'Ładowanie arkuszy stylów...'});
-       $.ajax({
-               url: STATIC_URL + 'xsl/wl2html_client.xsl',
-               dataType: 'xml',
-               success: function(data) {
-               xml2htmlStylesheet = createXSLT(data);
-                $.unblockUI();
-                               code_block();
-                 
-            },
-                       error: onError
-        })
-    }
-       else {
-               code_block();
-       }
-}
-
-
-function xml2html(options) {
-    withStylesheets(function() {
-        var xml = options.xml.replace(/\/\s+/g, '<br />');                             
-        var parser = new DOMParser();
-        var serializer = new XMLSerializer();
-        var doc = parser.parseFromString(xml, 'text/xml');             
-        var error = $('parsererror', doc);
-        
-        if (error.length == 0) {
-            doc = xml2htmlStylesheet.transformToFragment(doc, document);
-                       console.log(doc.firstChild);
-                       
-                       if(doc.firstChild === null) {
-                               options.error("Błąd w przetwarzaniu XML.");
-                               return;
-                       }
-                               
-            error = $('parsererror', doc);
-        }
-        
-        if (error.length > 0 && options.error) {
-            options.error(error.text());
-        } else {                       
-            options.success(doc.firstChild);
-        }
-    }, function() { options.error && options.error('Nie udało się załadować XSLT'); });
-}
-
-/* USEFULL CONSTANTS */
-const ELEMENT_NODE                                      = 1;
-const ATTRIBUTE_NODE                 = 2;
-const TEXT_NODE                      = 3;
-const CDATA_SECTION_NODE             = 4;
-const ENTITY_REFERENCE_NODE          = 5;
-const ENTITY_NODE                    = 6;
-const PROCESSING_INSTRUCTION_NODE    = 7;
-const COMMENT_NODE                   = 8;
-const DOCUMENT_NODE                  = 9;
-const DOCUMENT_TYPE_NODE             = 10;
-const DOCUMENT_FRAGMENT_NODE         = 11;
-const NOTATION_NODE                  = 12;
-const XATTR_RE = /^x-attr-name-(.*)$/;
-
-const ELEM_START = 1;
-const ELEM_END = 2;
-const NS_END = 3;
-
-const NAMESPACES = {
-       // namespaces not listed here will be assigned random names
-       "http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf",
-       "http://purl.org/dc/elements/1.1/": "dc",
-       "http://www.w3.org/XML/1998/namespace": "xml"
-};
-
-/*
- * PADDING for pretty-printing
- */
-const PADDING = {
-    dramat_wierszowany_l: 4,
-    dramat_wierszowany_lp: 4,
-    dramat_wspolczesny: 4,
-    wywiad: 4,
-    opowiadanie: 4,
-    powiesc: 4,
-    liryka_l: 4,
-    liryka_lp: 4,
-    naglowek_czesc: 4,
-    naglowek_akt: 4,
-    naglowek_rozdzial: 4,
-    naglowek_osoba: 4,
-    lista_osob: 4,
-    
-    akap: 3,
-    akap_cd: 3,
-    akap_dialog: 3,
-    strofa: 3,
-    motto: 3, 
-    miejsce_czas: 3,
-        
-    autor_utworu: 2,
-    nazwa_utworu: 2,
-    dzielo_nadrzedne: 2,
-       
-    didaskalia: 2,
-    motto_podpis: 2,
-    naglowek_listy: 2,
-    kwestia: 1,
-    lista_osoba: 1,
-       
-       "podpis": 1,    
-       "wers": 0,
-       "wers_cd": 0,
-       "wers_akap": 0,
-       "wers_wciety": 0,       
-       
-       "rdf:RDF": 3,
-       "rdf:Description": 1,   
-};
-
-function getPadding(name) {
-       
-       if(name.match(/^dc:.*$/))
-               return -1;
-       
-       if(PADDING[name])
-               return PADDING[name];
-               
-       return 0;
-}
-
-function HTMLSerializer() {    
-       // empty constructor
-}
-
-
-
-HTMLSerializer.prototype._prepare = function() {
-       this.stack = [];
-       
-       // XML namespace is implicit
-       this.nsMap = {"http://www.w3.org/XML/1998/namespace": "xml"};
-               
-       this.result = "";
-       this.nsCounter = 1;     
-}
-
-HTMLSerializer.prototype._pushElement = function(element) {
-       this.stack.push({
-               "type": ELEM_START,
-               "node": element
-       });     
-}
-
-HTMLSerializer.prototype._pushChildren = function(element) {
-       for(var i = element.childNodes.length-1; i >= 0; i--)
-               this._pushElement(element.childNodes.item(i));                                  
-}
-
-HTMLSerializer.prototype._pushTagEnd = function(tagName) {
-       this.stack.push({
-               "type": ELEM_END,
-               "tagName": tagName
-       });     
-}
-
-HTMLSerializer.prototype._verseBefore = function(node) {
-       var prev = node.previousSibling;
-       
-       while((prev !== null) && (prev.nodeType != ELEMENT_NODE)) {
-               prev = prev.previousSibling;
-       }       
-               
-       return (prev !== null) && prev.hasAttribute('x-verse');
-}
-
-HTMLSerializer.prototype.serialize = function(rootElement, stripOuter) 
-{
-       var self = this;
-       self._prepare();
-       
-       if(!stripOuter)
-               self._pushElement(rootElement);
-       else    
-               self._pushChildren(rootElement);
-       
-       while(self.stack.length > 0) {
-               var token = self.stack.pop();
-                                               
-               if(token.type === ELEM_END) {
-                       self.result += "</" + token.tagName + ">";                                      
-                       for(var padding = getPadding(token.tagName); padding > 0; padding--) {                  
-                               self.result += "\n";                    
-                       }
-                       continue;
-               };
-               
-               if(token.type === NS_END) {
-                       self._unassignNamespace(token.namespace);
-                       continue;
-               } 
-               
-               
-               switch(token.node.nodeType) {
-                       case ELEMENT_NODE:
-                               if(token.node.hasAttribute('x-pass-thru')) {
-                                       self._pushChildren(token.node);
-                                       break;
-                               }
-                               
-                               if(!token.node.hasAttribute('x-node'))
-                                       break;
-                                       
-                               var xnode = token.node.getAttribute('x-node');
-                               
-                               if(xnode === 'wers') {
-                                       /* push children */
-                                       if(self._verseBefore(token.node))
-                                               self.result += '/\n';
-                                       self._pushChildren(token.node);
-                                       break;                                  
-                               };                                      
-                               
-                               if(xnode === 'out-of-flow-text') {
-                                       self._pushChildren(token.node);
-                                       break;                                                                          
-                               }
-                               
-                               if(token.node.hasAttribute('x-verse') && self._verseBefore(token.node)) {
-                                       self.result += '/\n';                                   
-                               };
-                                       
-                               self._serializeElement(token.node);
-                               break;
-                       case TEXT_NODE:
-                               self.result += token.node.nodeValue;
-                               break;
-               };
-       };
-       
-       return this.result;
-}
-
-/*
- * TODO: this doesn't support prefix redefinitions
- */
-HTMLSerializer.prototype._unassignNamespace = function(nsData) {
-       this.nsMap[nsData.uri] = undefined;
-};
-       
-HTMLSerializer.prototype._assignNamespace = function(uri) {
-       if(uri === null) {
-               // default namespace
-               return ({"prefix": "", "uri": "", "fresh": false});
-       }
-       
-       if(this.nsMap[uri] === undefined) {
-               // this prefix hasn't been defined yet in current context       
-               var prefix = NAMESPACES[uri];
-               
-               if (prefix === undefined) { // not predefined
-                       prefix = "ns" + this.nsCounter;
-                       this.nsCounter += 1;
-               }
-               
-               this.nsMap[uri] = prefix;               
-               return ({
-                       "prefix": prefix,
-                       "uri": uri,
-                       "fresh": true
-               });                     
-       }       
-               
-       return ({"prefix": this.nsMap[uri], "uri": uri, "fresh": false});               
-};
-
-HTMLSerializer.prototype._join = function(prefix, name) {
-       if(!!prefix) 
-               return prefix + ":" + name;
-       return name;    
-};
-
-HTMLSerializer.prototype._rjoin = function(prefix, name) {
-       if(!!name) 
-               return prefix + ":" + name;
-       return prefix;  
-};
-                                       
-HTMLSerializer.prototype._serializeElement = function(node) {
-       var self = this;
-               
-       var ns = node.getAttribute('x-ns');
-       var nsPrefix = null;
-       var newNamespaces = [];
-       
-       var nsData = self._assignNamespace(node.getAttribute('x-ns'));
-       
-       if(nsData.fresh) {
-               newNamespaces.push(nsData);
-               self.stack.push({
-                       "type": NS_END,
-                       "namespace": nsData
-               });
-       }                                       
-       
-       var tagName = self._join(nsData.prefix, node.getAttribute('x-node'));
-                               
-       /* retrieve attributes */
-       var attributeIDs = [];
-       for (var i = 0; i < node.attributes.length; i++) {
-               var attr = node.attributes.item(i);
-               
-               // check if name starts with "x-attr-name"
-               var m = attr.name.match(XATTR_RE);
-               if (m !== null) 
-                       attributeIDs.push(m[1]);                                
-       };
-                               
-       /* print out */
-       if (getPadding(tagName))
-               self.result += '\n';
-               
-       self.result += '<' + tagName;   
-                                       
-       $.each(attributeIDs, function() {
-               var nsData = self._assignNamespace(node.getAttribute('x-attr-ns-'+this));
-       
-               if(nsData.fresh) {
-                       newNamespaces.push(nsData);
-                       self.stack.push({
-                               "type": NS_END,
-                               "namespace": nsData
-                       });
-               };
-                                                                                                                       
-               self.result += ' ' + self._join(nsData.prefix, node.getAttribute('x-attr-name-'+this));
-               self.result += '="'+node.getAttribute('x-attr-value-'+this) +'"';
-       });
-       
-       /* print new namespace declarations */
-       $.each(newNamespaces, function() {
-               self.result += " " + self._rjoin("xmlns", this.prefix);
-               self.result += '="' + this.uri + '"';           
-       });                                     
-       
-       if (node.childNodes.length > 0) {
-               self.result += ">";
-               self._pushTagEnd(tagName);
-               self._pushChildren(node);
-       }
-       else {
-               self.result += "/>";
-       };
-};
-
-function html2text(params) {   
-       try {
-               var s = new HTMLSerializer();
-               params.success( s.serialize(params.element, params.stripOuter) );
-       } catch(e) {
-               params.error("Nie udało się zserializować tekstu:" + e)
-       }       
-}
\ No newline at end of file