html preview imported from WL
authorMarcin Koziej <marcin.koziej@nowoczesnapolska.org.pl>
Thu, 26 Apr 2012 09:45:11 +0000 (11:45 +0200)
committerMarcin Koziej <marcin.koziej@nowoczesnapolska.org.pl>
Thu, 26 Apr 2012 09:45:11 +0000 (11:45 +0200)
apps/catalogue/templates/catalogue/book_text.html [new file with mode: 0644]
apps/catalogue/views.py
redakcja/static/css/book.css [new file with mode: 0644]
redakcja/static/icons/revert_.png [new file with mode: 0755]
redakcja/static/img/arrow-down.png [new file with mode: 0644]
redakcja/static/img/arrow-up.png [new file with mode: 0644]
redakcja/static/img/logo-220.png [new file with mode: 0644]
redakcja/static/js/book_text/book.js [new file with mode: 0644]
redakcja/static/js/book_text/jquery.eventdelegation.js [new file with mode: 0644]
redakcja/static/js/book_text/jquery.highlightfade.js [new file with mode: 0644]
redakcja/static/js/book_text/jquery.scrollto.js [new file with mode: 0644]

diff --git a/apps/catalogue/templates/catalogue/book_text.html b/apps/catalogue/templates/catalogue/book_text.html
new file mode 100644 (file)
index 0000000..dc7a80d
--- /dev/null
@@ -0,0 +1,32 @@
+{% load i18n %}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+        <title>{% trans "Redakcja" %} :: {{ book.title }}</title>
+       <link rel="stylesheet" type="text/css" href="/media/static/css/book.css" />
+        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
+       <script type="text/javascript" src="/media/static/js/book_text/jquery.eventdelegation.js"></script>
+       <script type="text/javascript" src="/media/static/js/book_text/jquery.scrollto.js"></script>
+       <script type="text/javascript" src="/media/static/js/book_text/jquery.highlightfade.js"></script>
+       <script type="text/javascript" src="/media/static/js/book_text/book.js"></script>
+
+    </head>
+    <body>
+        <div id="menu">
+            <ul>
+                <li><a class="menu" href="#toc">{% trans "Table of contents" %}</a></li>
+{#                <li><a class="menu" href="#themes">{% trans "Themes" %}</a></li>#}
+                <li><a class="menu" href="#nota_red">{% trans "Edit. note" %}</a></li>
+{#                <li><a class="menu" href="#info">{% trans "Infobox" %}</a></li>#}
+{#                <li><a href="{{ book.get_absolute_url }}">{% trans "Book's page" %}</a></li> #}
+{#                <li><a class="menu" href="#download">{% trans "Download" %}</a></li>#}
+            </ul>
+        </div>
+        <div id="header">
+            <a href="/"><img src="/media/static/img/logo-220.png" alt="Wolne Lektury" /></a>
+        </div>
+        {{ html|safe }}
+    </body>
+</html>
index 2ee94ae..d0213da 100644 (file)
@@ -12,12 +12,13 @@ from django.core.urlresolvers import reverse
 from django.db.models import Count, Q
 from django import http
 from django.http import Http404, HttpResponse, HttpResponseForbidden
 from django.db.models import Count, Q
 from django import http
 from django.http import Http404, HttpResponse, HttpResponseForbidden
-from django.shortcuts import get_object_or_404, render
+from django.shortcuts import get_object_or_404, render, render_to_response
 from django.utils.encoding import iri_to_uri
 from django.utils.http import urlquote_plus
 from django.utils.translation import ugettext_lazy as _
 from django.views.decorators.http import require_POST
 from django.views.generic.simple import direct_to_template
 from django.utils.encoding import iri_to_uri
 from django.utils.http import urlquote_plus
 from django.utils.translation import ugettext_lazy as _
 from django.views.decorators.http import require_POST
 from django.views.generic.simple import direct_to_template
+from django.template import RequestContext
 
 from apiclient import NotAuthorizedError
 from catalogue import forms
 
 from apiclient import NotAuthorizedError
 from catalogue import forms
@@ -225,10 +226,20 @@ def book_html(request, slug):
         return HttpResponseForbidden("Not authorized.")
 
     doc = book.wldocument(parse_dublincore=False)
         return HttpResponseForbidden("Not authorized.")
 
     doc = book.wldocument(parse_dublincore=False)
-    html = doc.as_html(flags=['full-page'])
+    html = doc.as_html()
+
     html = html.get_string() if html is not None else ''
     html = html.get_string() if html is not None else ''
-    response = http.HttpResponse(html, content_type='text/html', mimetype='text/html')
-    return response
+    # response = http.HttpResponse(html, content_type='text/html', mimetype='text/html')
+    # return response
+    # book_themes = {}
+    # for fragment in book.fragments.all().iterator():
+    #     for theme in fragment.tags.filter(category='theme').iterator():
+    #         book_themes.setdefault(theme, []).append(fragment)
+
+    # book_themes = book_themes.items()
+    # book_themes.sort(key=lambda s: s[0].sort_key)
+    return render_to_response('catalogue/book_text.html', locals(),
+        context_instance=RequestContext(request))
 
 
 @never_cache
 
 
 @never_cache
diff --git a/redakcja/static/css/book.css b/redakcja/static/css/book.css
new file mode 100644 (file)
index 0000000..354a839
--- /dev/null
@@ -0,0 +1,406 @@
+body {
+    font-size: 16px;
+    font: Georgia, "Times New Roman", serif;
+    line-height: 1.5em;
+    margin: 0;
+}
+
+a {
+    color: blue;
+    text-decoration: none;
+}
+
+#book-text {
+    margin: 3em;
+    max-width: 36em;
+}
+
+/* ================================== */
+/* = Header with logo and menu      = */
+/* ================================== */
+#header {
+    margin: 3.4em 0 0 1.4em;
+}
+
+img {
+    border: none;
+}
+
+#logo {
+    font-size: 1.5em;
+}
+#logo a {
+    color: black;
+}
+
+#menu {
+    position: fixed;
+    left: 0em;
+    top: 0em;
+    width: 100%;
+    height: 1.5em;
+    background: #333;
+    color: #FFF;
+    opacity: 0.9;
+    z-index: 99;
+}
+
+#menu ul {
+    list-style: none;
+    padding: 0;
+    margin: 0;
+}
+
+#menu li a {
+    display: block;
+    float: left;
+    height: 1.5em;
+    margin-left: 0.5em;
+    text-align: center;
+    color: #FFF;
+    padding: 0 1em;
+}
+#menu li a.menu {
+    padding-right: 1.5em;
+}
+
+#menu li a.menu:hover, #menu li a.menu:active {
+    color: #000;
+    background: #FFF url(/media/static/img/arrow-down.png) no-repeat center right;
+}
+
+#menu li a.menu.selected {
+    color: #000;
+    background: #FFF url(/media/static/img/arrow-up.png) no-repeat center right;
+}
+#menu a.menu-link {
+    display: block;
+    float: left;
+    height: 1.5em;
+    margin-left: 0.5em;
+    text-align: center;
+    color: #FFF;
+}
+#menu span {
+    color: #888;
+    font-style: italic;
+    font-size: .75em;
+    margin-right: 0.5em;
+}
+
+
+#toc, #themes, #nota_red, #info {
+    position: fixed;
+    left: 0em;
+    top: 1.5em;
+    width: 37em;
+    padding: 1.5em;
+    background: #FFF;
+    border-bottom: 0.25em solid #DDD;
+    border-right: 0.25em solid #DDD;
+    display: none;
+    height: 16em;
+    overflow-x: hidden;
+    overflow-y: auto;
+    opacity: 0.9;
+    z-index: 99;
+}
+#download {
+    position: fixed;
+    left: 0em;
+    top: 1.5em;
+    width: 37em;
+    padding: 1.5em;
+    background: #FFF;
+    border-bottom: 0.25em solid #DDD;
+    border-right: 0.25em solid #DDD;
+    display: none;
+    height: 10em;
+    overflow-x: hidden;
+    overflow-y: auto;
+    opacity: 0.9;
+    z-index: 99;
+}
+
+#toc ol, #themes ol {
+    list-style: none;
+    padding: 0;
+    margin: 0;
+}
+
+#toc ol li {
+    font-weight: bold;
+}
+
+#toc ol ol {
+    padding: 0 0 1.5em 1.5em;
+    margin: 0;
+}
+
+#toc ol ol li {
+    font-weight: normal;
+}
+
+#toc h2 {
+    display: none;
+}
+
+#toc .anchor {
+    float: none;
+    margin: 0;
+    color: blue;
+    font-size: 16px;
+    position: inherit;
+}
+
+#info p {
+    text-align: justify;
+    margin: 1.5em 0 0;
+}
+
+/* =================================================== */
+/* = Common elements: headings, paragraphs and lines = */
+/* =================================================== */
+h1 {
+    font-size: 3em;
+    margin: 1.5em 0;
+    text-align: center;
+    line-height: 1.5em;
+    font-weight: bold;
+}
+
+h2 {
+    font-size: 2em;
+    margin: 1.5em 0 0;
+    font-weight: bold;
+    line-height: 1.5em;
+}
+
+h3 {
+    font-size: 1.5em;
+    margin: 1.5em 0 0;
+    font-weight: normal;
+    line-height: 1.5em;
+}
+
+h4 {
+    font-size: 1em;
+    margin: 1.5em 0 0;
+    line-height: 1.5em;
+}
+
+p {
+    margin: 0;
+}
+
+/* ======================== */
+/* = Footnotes and themes = */
+/* ======================== */
+.theme-begin {
+    border-left: 0.1em solid #DDDDDD;
+    color: #777;
+    padding: 0 0.5em;
+    width: 7.5em;
+
+    font-style: normal;
+    font-weight: normal;
+    font-variant: normal;
+    letter-spacing: 0;
+    text-transform: none;
+    text-decoration: none;
+
+    font-size: 16px;
+    float: right;
+    margin-right: -9.5em;
+    margin-bottom: 0.5em;
+    clear: both;
+    left: 40em;
+    line-height: 1.5em;
+    text-align: left;
+}
+
+.annotation {
+    font-style: normal;
+    font-weight: normal;
+    font-size: 12px;
+    padding-left: 2px;
+    position: relative;
+    top: -4px;
+}
+
+#footnotes {
+    margin-top: 3em;
+}
+
+#footnotes .annotation {
+    display: block;
+    float: left;
+    width: 2.5em;
+    clear: both;
+}
+
+#footnotes div {
+    margin: 1.5em 0 0 0;
+}
+
+#footnotes p, #footnotes ul {
+    margin-left: 2.5em;
+    font-size: 0.875em;
+}
+
+#footnotes .permalink {
+    font-size: .75em;
+}
+
+blockquote {
+    font-size: 0.875em;
+}
+
+/* ============= */
+/* = Numbering = */
+/* ============= */
+.verse, .paragraph {
+    position:relative;
+}
+.anchor {
+    position: absolute;
+    margin: -0.25em -0.5em;
+    left: -3em;
+    color: #777;
+    font-size: 12px;
+    width: 2em;
+    text-align: center;
+    padding: 0.25em 0.5em;
+    line-height: 1.5em;
+}
+
+.anchor:hover, #book-text .anchor:active {
+    color: #FFF;
+    background-color: #CCC;
+}
+
+/* =================== */
+/* = Custom elements = */
+/* =================== */
+span.author {
+    font-size: 0.5em;
+    display: block;
+    line-height: 1.5em;
+    margin-bottom: 0.25em;
+}
+
+span.collection {
+    font-size: 0.375em;
+    display: block;
+    line-height: 1.5em;
+    margin-bottom: -0.25em;
+}
+
+span.subtitle {
+    font-size: 0.5em;
+    display: block;
+    line-height: 1.5em;
+    margin-top: -0.25em;
+}
+
+span.translator {
+    font-size: 0.375em;
+    display: block;
+    line-height: 1.5em;
+    margin-top: 0.25em;
+}
+
+div.didaskalia {
+    font-style: italic;
+    margin: 0.5em 0 0 1.5em;
+}
+
+div.kwestia {
+    margin: 0.5em 0 0;
+}
+
+div.stanza {
+    margin: 1.5em 0 0;
+}
+
+div.kwestia div.stanza {
+    margin: 0;
+}
+
+p.paragraph {
+    text-align: justify;
+    margin: 1.5em 0 0;
+}
+
+p.motto {
+    text-align: justify;
+    font-style: italic;
+    margin: 1.5em 0 0;
+}
+
+p.motto_podpis {
+    font-size: 0.875em;
+    text-align: right;
+}
+
+div.fragment {
+    border-bottom: 0.1em solid #999;
+    padding-bottom: 1.5em;
+}
+
+div.note p, div.dedication p, div.note p.paragraph, div.dedication p.paragraph {
+    text-align: right;
+    font-style: italic;
+}
+
+hr.spacer {
+    height: 3em;
+    visibility: hidden;
+}
+
+hr.spacer-line {
+    margin: 1.5em 0;
+    border: none;
+    border-bottom: 0.1em solid #000;
+}
+
+p.spacer-asterisk {
+    padding: 0;
+    margin: 1.5em 0;
+    text-align: center;
+}
+
+div.person-list ol {
+    list-style: none;
+    padding: 0 0 0 1.5em;
+}
+
+p.place-and-time {
+    font-style: italic;
+}
+
+em.math, em.foreign-word, em.book-title, em.didaskalia {
+    font-style: italic;
+}
+
+em.author-emphasis {
+    letter-spacing: 0.1em;
+}
+
+em.person {
+    font-style: normal;
+    font-variant: small-caps;
+}
+
+.verse:after {
+    content: "\feff";
+}
+
+
+/* =================================== */
+/* = Hide some elements for printing = */
+/* =================================== */
+
+@media print {
+    #menu {display: none;}
+}
diff --git a/redakcja/static/icons/revert_.png b/redakcja/static/icons/revert_.png
new file mode 100755 (executable)
index 0000000..afdf20d
Binary files /dev/null and b/redakcja/static/icons/revert_.png differ
diff --git a/redakcja/static/img/arrow-down.png b/redakcja/static/img/arrow-down.png
new file mode 100644 (file)
index 0000000..0e32315
Binary files /dev/null and b/redakcja/static/img/arrow-down.png differ
diff --git a/redakcja/static/img/arrow-up.png b/redakcja/static/img/arrow-up.png
new file mode 100644 (file)
index 0000000..cdf9cf6
Binary files /dev/null and b/redakcja/static/img/arrow-up.png differ
diff --git a/redakcja/static/img/logo-220.png b/redakcja/static/img/logo-220.png
new file mode 100644 (file)
index 0000000..9b15e88
Binary files /dev/null and b/redakcja/static/img/logo-220.png differ
diff --git a/redakcja/static/js/book_text/book.js b/redakcja/static/js/book_text/book.js
new file mode 100644 (file)
index 0000000..335fe39
--- /dev/null
@@ -0,0 +1,61 @@
+$(function() {
+    function scrollToAnchor(anchor) {
+        if (anchor) {
+            var anchor_name = anchor.slice(1);
+            var element = $('a[name="' + anchor_name + '"]');
+            if (element.length > 0) {
+                $.scrollTo(element, 500, {offset: {top: -50, left: 0}});
+                foot_elem = $('#footnotes a[name="' + anchor_name + '"]');
+                if (foot_elem.length > 0) {
+                    $(element).parent().highlightFade('yellow');
+                }
+                window.location.hash = anchor;
+            }
+        }
+    }
+
+    $.highlightFade.defaults.speed = 3000;
+    $('#toc').hide();
+    if ($('#toc li').length == 0) {
+        $('#menu li a[href="#toc"]').remove();
+    }
+    if ($('#nota_red').length == 0) {
+        $('#menu li a[href="#nota_red"]').remove();
+    }
+
+    // On page load, scroll to anchor
+    scrollToAnchor(window.location.hash)
+
+    $('#toc, #themes, #book-text').delegate('click', 'a', function(event) {
+        event.preventDefault();
+        $('#menu li a.selected').click();
+        scrollToAnchor($(this).attr('href'));
+    });
+
+    $('#menu li a.menu').toggle(function() {
+        $('#menu li a.selected').click();
+        $(this).addClass('selected');
+        $($(this).attr('href')).slideDown('fast');
+    }, function() {
+        $(this).removeClass('selected');
+        $($(this).attr('href')).slideUp('fast');
+    });
+    
+
+    if (window.getSelection) {
+        $('.theme-begin').click(function() {
+            var selection = window.getSelection();
+            selection.removeAllRanges();
+            var range = document.createRange();
+
+            var e = $(".theme-end[fid='" + $(this).attr('fid') + "']")[0];
+
+            if (e) {
+                range.setStartAfter(this);
+                range.setEndBefore(e);
+                selection.addRange(range);
+            }
+        });
+    }
+
+});
diff --git a/redakcja/static/js/book_text/jquery.eventdelegation.js b/redakcja/static/js/book_text/jquery.eventdelegation.js
new file mode 100644 (file)
index 0000000..52fce07
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * jQuery Event Delegation Plugin - jquery.eventdelegation.js
+ * Fast flexible event handling
+ *
+ * January 2008 - Randy Morey (http://dev.distilldesign.com/)
+ */
+
+(function ($) {
+       /* setup list of allowed events for event delegation
+        * only events that bubble are appropriate
+        */
+       var allowed = {};
+       $.each([
+               'click',
+               'dblclick',
+               'mousedown',
+               'mouseup',
+               'mousemove',
+               'mouseover',
+               'mouseout',
+               'keydown',
+               'keypress',
+               'keyup'
+               ], function(i, eventName) {
+                       allowed[eventName] = true;
+       });
+
+       $.fn.extend({
+               delegate: function (event, selector, f) {
+                       return $(this).each(function () {
+                               if (allowed[event])
+                                       $(this).bind(event, function (e) {
+                                               var el = $(e.target),
+                                                       result = false;
+
+                                               while (!$(el).is('body')) {
+                                                       if ($(el).is(selector)) {
+                                                               result = f.apply($(el)[0], [e]);
+                                                               if (result === false)
+                                                                       e.preventDefault();
+                                                               return;
+                                                       }
+
+                                                       el = $(el).parent();
+                                               }
+                                       });
+                       });
+               },
+               undelegate: function (event) {
+                       return $(this).each(function () {
+                               $(this).unbind(event);
+                       });
+               }
+       });
+})(jQuery);
\ No newline at end of file
diff --git a/redakcja/static/js/book_text/jquery.highlightfade.js b/redakcja/static/js/book_text/jquery.highlightfade.js
new file mode 100644 (file)
index 0000000..bbe39f0
--- /dev/null
@@ -0,0 +1,150 @@
+/**
+ *  jQuery Plugin highlightFade (jquery.offput.ca/highlightFade)
+ *  (c) 2006 Blair Mitchelmore (offput.ca) blair@offput.ca
+ */
+/**
+ * This is version 0.7 of my highlightFade plugin. It follows the yellow fade technique of Web 2.0 fame
+ * but expands it to allow any starting colour and allows you to specify the end colour as well.
+ *
+ * For the moment, I'm done with this plug-in. Unless I come upon a really cool feature it should have
+ * this plug-in will only receive updates to ensure future compatibility with jQuery.
+ *
+ * As of now (Aug. 16, 2006) the plugin has been written with the 1.0.1 release of jQuery (rev 249) which
+ * is available from http://jquery.com/src/jquery-1.0.1.js
+ *
+ * A note regarding rgb() syntax: I noticed that most browsers implement rgb syntax as either an integer
+ * (0-255) or percentage (0-100%) value for each field, that is, rgb(i/p,i/p,i/p); however, the W3C
+ * standard clearly defines it as "either three integer values or three percentage values" [http://www.w3.org/TR/CSS21/syndata.html]
+ * which I choose to follow despite the error redundancy of the typical behaviour browsers employ.
+ *
+ * Changelog:
+ *
+ *    0.7:
+ *        - Added the awesome custom attribute support written by George Adamson (slightly modified)
+ *        - Removed bgColor plugin dependency seeing as attr is customizable now...
+ *    0.6:
+ *        - Abstracted getBGColor into its own plugin with optional test and data retrieval functions
+ *        - Converted all $ references to jQuery references as John's code seems to be shifting away
+ *          from that and I don't want to have to update this for a long time.
+ *    0.5:
+ *        - Added simple argument syntax for only specifying start colour of event
+ *        - Removed old style argument syntax
+ *        - Added 'interval', 'final, and 'end' properties
+ *        - Renamed 'color' property to 'start'
+ *        - Added second argument to $.highlightFade.getBGColor to bypass the e.highlighting check
+ *    0.4:
+ *        - Added rgb(%,%,%) color syntax
+ *    0.3:
+ *        - Fixed bug when event was called while parent was also running event corrupting the
+ *          the background colour of the child
+ *    0.2:
+ *        - Fixed bug where an unspecified onComplete function made the page throw continuous errors
+ *        - Fixed bug where multiple events on the same element would speed each subsequent event
+ *    0.1:
+ *        - Initial Release
+ *
+ * @author          Blair Mitchelmore (blair@offput.ca)
+ * @version         0.5
+ */
+jQuery.fn.highlightFade = function(settings) {
+       var o = (settings && settings.constructor == String) ? {start: settings} : settings || {};
+       var d = jQuery.highlightFade.defaults;
+       var i = o['interval'] || d['interval'];
+       var a = o['attr'] || d['attr'];
+       var ts = {
+               'linear': function(s,e,t,c) { return parseInt(s+(c/t)*(e-s)); },
+               'sinusoidal': function(s,e,t,c) { return parseInt(s+Math.sin(((c/t)*90)*(Math.PI/180))*(e-s)); },
+               'exponential': function(s,e,t,c) { return parseInt(s+(Math.pow(c/t,2))*(e-s)); }
+       };
+       var t = (o['iterator'] && o['iterator'].constructor == Function) ? o['iterator'] : ts[o['iterator']] || ts[d['iterator']] || ts['linear'];
+       if (d['iterator'] && d['iterator'].constructor == Function) t = d['iterator'];
+       return this.each(function() {
+               if (!this.highlighting) this.highlighting = {};
+               var e = (this.highlighting[a]) ? this.highlighting[a].end : jQuery.highlightFade.getBaseValue(this,a) || [255,255,255];
+               var c = jQuery.highlightFade.getRGB(o['start'] || o['colour'] || o['color'] || d['start'] || [255,255,128]);
+               var s = jQuery.speed(o['speed'] || d['speed']);
+               var r = o['final'] || (this.highlighting[a] && this.highlighting[a].orig) ? this.highlighting[a].orig : jQuery.curCSS(this,a);
+               if (o['end'] || d['end']) r = jQuery.highlightFade.asRGBString(e = jQuery.highlightFade.getRGB(o['end'] || d['end']));
+               if (typeof o['final'] != 'undefined') r = o['final'];
+               if (this.highlighting[a] && this.highlighting[a].timer) window.clearInterval(this.highlighting[a].timer);
+               this.highlighting[a] = { steps: ((s.duration) / i), interval: i, currentStep: 0, start: c, end: e, orig: r, attr: a };
+               jQuery.highlightFade(this,a,o['complete'],t);
+       });
+};
+
+jQuery.highlightFade = function(e,a,o,t) {
+       e.highlighting[a].timer = window.setInterval(function() {
+               var newR = t(e.highlighting[a].start[0],e.highlighting[a].end[0],e.highlighting[a].steps,e.highlighting[a].currentStep);
+               var newG = t(e.highlighting[a].start[1],e.highlighting[a].end[1],e.highlighting[a].steps,e.highlighting[a].currentStep);
+               var newB = t(e.highlighting[a].start[2],e.highlighting[a].end[2],e.highlighting[a].steps,e.highlighting[a].currentStep);
+               jQuery(e).css(a,jQuery.highlightFade.asRGBString([newR,newG,newB]));
+               if (e.highlighting[a].currentStep++ >= e.highlighting[a].steps) {
+                       jQuery(e).css(a,e.highlighting[a].orig || '');
+                       window.clearInterval(e.highlighting[a].timer);
+                       e.highlighting[a] = null;
+                       if (o && o.constructor == Function) o.call(e);
+               }
+       },e.highlighting[a].interval);
+};
+
+jQuery.highlightFade.defaults = {
+       start: [255,255,128],
+       interval: 50,
+       speed: 400,
+       attr: 'backgroundColor'
+};
+
+jQuery.highlightFade.getRGB = function(c,d) {
+       var result;
+       if (c && c.constructor == Array && c.length == 3) return c;
+       if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))
+               return [parseInt(result[1]),parseInt(result[2]),parseInt(result[3])];
+       else if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))
+               return [parseFloat(result[1])*2.55,parseFloat(result[2])*2.55,parseFloat(result[3])*2.55];
+       else if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))
+               return [parseInt("0x" + result[1]),parseInt("0x" + result[2]),parseInt("0x" + result[3])];
+       else if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))
+               return [parseInt("0x"+ result[1] + result[1]),parseInt("0x" + result[2] + result[2]),parseInt("0x" + result[3] + result[3])];
+       else
+               return jQuery.highlightFade.checkColorName(c) || d || null;
+};
+
+jQuery.highlightFade.asRGBString = function(a) {
+       return "rgb(" + a.join(",") + ")";
+};
+
+jQuery.highlightFade.getBaseValue = function(e,a,b) {
+       var s, t;
+       b = b || false;
+       t = a = a || jQuery.highlightFade.defaults['attr'];
+       do {
+               s = jQuery(e).css(t || 'backgroundColor');
+               if ((s  != '' && s != 'transparent') || (e.tagName.toLowerCase() == "body") || (!b && e.highlighting && e.highlighting[a] && e.highlighting[a].end)) break;
+               t = false;
+       } while (e = e.parentNode);
+       if (!b && e.highlighting && e.highlighting[a] && e.highlighting[a].end) s = e.highlighting[a].end;
+       if (s == undefined || s == '' || s == 'transparent') s = [255,255,255];
+       return jQuery.highlightFade.getRGB(s);
+};
+
+jQuery.highlightFade.checkColorName = function(c) {
+       if (!c) return null;
+       switch(c.replace(/^\s*|\s*$/g,'').toLowerCase()) {
+               case 'aqua': return [0,255,255];
+               case 'black': return [0,0,0];
+               case 'blue': return [0,0,255];
+               case 'fuchsia': return [255,0,255];
+               case 'gray': return [128,128,128];
+               case 'green': return [0,128,0];
+               case 'lime': return [0,255,0];
+               case 'maroon': return [128,0,0];
+               case 'navy': return [0,0,128];
+               case 'olive': return [128,128,0];
+               case 'purple': return [128,0,128];
+               case 'red': return [255,0,0];
+               case 'silver': return [192,192,192];
+               case 'teal': return [0,128,128];
+               case 'white': return [255,255,255];
+               case 'yellow': return [255,255,0];
+       }
+};
diff --git a/redakcja/static/js/book_text/jquery.scrollto.js b/redakcja/static/js/book_text/jquery.scrollto.js
new file mode 100644 (file)
index 0000000..c403ab9
--- /dev/null
@@ -0,0 +1,194 @@
+/**
+ * jQuery.ScrollTo
+ * Copyright (c) 2007-2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
+ * Dual licensed under MIT and GPL.
+ * Date: 9/11/2008
+ *
+ * @projectDescription Easy element scrolling using jQuery.
+ * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
+ * Tested with jQuery 1.2.6. On FF 2/3, IE 6/7, Opera 9.2/5 and Safari 3. on Windows.
+ *
+ * @author Ariel Flesler
+ * @version 1.4
+ *
+ * @id jQuery.scrollTo
+ * @id jQuery.fn.scrollTo
+ * @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements.
+ *       The different options for target are:
+ *             - A number position (will be applied to all axes).
+ *             - A string position ('44', '100px', '+=90', etc ) will be applied to all axes
+ *             - A jQuery/DOM element ( logically, child of the element to scroll )
+ *             - A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc )
+ *             - A hash { top:x, left:y }, x and y can be any kind of number/string like above.
+ * @param {Number} duration The OVERALL length of the animation, this argument can be the settings object instead.
+ * @param {Object,Function} settings Optional set of settings or the onAfter callback.
+ *      @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'.
+ *      @option {Number} duration The OVERALL length of the animation.
+ *      @option {String} easing The easing method for the animation.
+ *      @option {Boolean} margin If true, the margin of the target element will be deducted from the final position.
+ *      @option {Object, Number} offset Add/deduct from the end position. One number for both axes or { top:x, left:y }.
+ *      @option {Object, Number} over Add/deduct the height/width multiplied by 'over', can be { top:x, left:y } when using both axes.
+ *      @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends.
+ *      @option {Function} onAfter Function to be called after the scrolling ends.
+ *      @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends.
+ * @return {jQuery} Returns the same jQuery object, for chaining.
+ *
+ * @desc Scroll to a fixed position
+ * @example $('div').scrollTo( 340 );
+ *
+ * @desc Scroll relatively to the actual position
+ * @example $('div').scrollTo( '+=340px', { axis:'y' } );
+ *
+ * @dec Scroll using a selector (relative to the scrolled element)
+ * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } );
+ *
+ * @ Scroll to a DOM element (same for jQuery object)
+ * @example var second_child = document.getElementById('container').firstChild.nextSibling;
+ *                     $('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){
+ *                             alert('scrolled!!');
+ *                     }});
+ *
+ * @desc Scroll on both axes, to different values
+ * @example $('div').scrollTo( { top: 300, left:'+=200' }, { axis:'xy', offset:-20 } );
+ */
+;(function( $ ){
+
+       var $scrollTo = $.scrollTo = function( target, duration, settings ){
+               $(window).scrollTo( target, duration, settings );
+       };
+
+       $scrollTo.defaults = {
+               axis:'y',
+               duration:1
+       };
+
+       // Returns the element that needs to be animated to scroll the window.
+       // Kept for backwards compatibility (specially for localScroll & serialScroll)
+       $scrollTo.window = function( scope ){
+               return $(window).scrollable();
+       };
+
+       // Hack, hack, hack... stay away!
+       // Returns the real elements to scroll (supports window/iframes, documents and regular nodes)
+       $.fn.scrollable = function(){
+               return this.map(function(){
+                       // Just store it, we might need it
+                       var win = this.parentWindow || this.defaultView,
+                               // If it's a document, get its iframe or the window if it's THE document
+                               elem = this.nodeName == '#document' ? win.frameElement || win : this,
+                               // Get the corresponding document
+                               doc = elem.contentDocument || (elem.contentWindow || elem).document,
+                               isWin = elem.setInterval;
+
+                       return elem.nodeName == 'IFRAME' || isWin && $.browser.safari ? doc.body
+                               : isWin ? doc.documentElement
+                               : this;
+               });
+       };
+
+       $.fn.scrollTo = function( target, duration, settings ){
+               if( typeof duration == 'object' ){
+                       settings = duration;
+                       duration = 0;
+               }
+               if( typeof settings == 'function' )
+                       settings = { onAfter:settings };
+
+               settings = $.extend( {}, $scrollTo.defaults, settings );
+               // Speed is still recognized for backwards compatibility
+               duration = duration || settings.speed || settings.duration;
+               // Make sure the settings are given right
+               settings.queue = settings.queue && settings.axis.length > 1;
+
+               if( settings.queue )
+                       // Let's keep the overall duration
+                       duration /= 2;
+               settings.offset = both( settings.offset );
+               settings.over = both( settings.over );
+
+               return this.scrollable().each(function(){
+                       var elem = this,
+                               $elem = $(elem),
+                               targ = target, toff, attr = {},
+                               win = $elem.is('html,body');
+
+                       switch( typeof targ ){
+                               // A number will pass the regex
+                               case 'number':
+                               case 'string':
+                                       if( /^([+-]=)?\d+(px)?$/.test(targ) ){
+                                               targ = both( targ );
+                                               // We are done
+                                               break;
+                                       }
+                                       // Relative selector, no break!
+                                       targ = $(targ,this);
+                               case 'object':
+                                       // DOMElement / jQuery
+                                       if( targ.is || targ.style )
+                                               // Get the real position of the target
+                                               toff = (targ = $(targ)).offset();
+                       }
+                       $.each( settings.axis.split(''), function( i, axis ){
+                               var Pos = axis == 'x' ? 'Left' : 'Top',
+                                       pos = Pos.toLowerCase(),
+                                       key = 'scroll' + Pos,
+                                       old = elem[key],
+                                       Dim = axis == 'x' ? 'Width' : 'Height',
+                                       dim = Dim.toLowerCase();
+
+                               if( toff ){// jQuery / DOMElement
+                                       attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] );
+
+                                       // If it's a dom element, reduce the margin
+                                       if( settings.margin ){
+                                               attr[key] -= parseInt(targ.css('margin'+Pos)) || 0;
+                                               attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0;
+                                       }
+
+                                       attr[key] += settings.offset[pos] || 0;
+
+                                       if( settings.over[pos] )
+                                               // Scroll to a fraction of its width/height
+                                               attr[key] += targ[dim]() * settings.over[pos];
+                               }else
+                                       attr[key] = targ[pos];
+
+                               // Number or 'number'
+                               if( /^\d+$/.test(attr[key]) )
+                                       // Check the limits
+                                       attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max(Dim) );
+
+                               // Queueing axes
+                               if( !i && settings.queue ){
+                                       // Don't waste time animating, if there's no need.
+                                       if( old != attr[key] )
+                                               // Intermediate animation
+                                               animate( settings.onAfterFirst );
+                                       // Don't animate this axis again in the next iteration.
+                                       delete attr[key];
+                               }
+                       });
+                       animate( settings.onAfter );
+
+                       function animate( callback ){
+                               $elem.animate( attr, duration, settings.easing, callback && function(){
+                                       callback.call(this, target, settings);
+                               });
+                       };
+                       function max( Dim ){
+                               var attr ='scroll'+Dim,
+                                       doc = elem.ownerDocument;
+
+                               return win
+                                               ? Math.max( doc.documentElement[attr], doc.body[attr]  )
+                                               : elem[attr];
+                       };
+               }).end();
+       };
+
+       function both( val ){
+               return typeof val == 'object' ? val : { top:val, left:val };
+       };
+
+})( jQuery );
\ No newline at end of file