integration/js/annotation-article.js
changeset 31 059e197617bb
child 32 3612737630f4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/integration/js/annotation-article.js	Wed Jun 19 18:28:56 2013 +0200
@@ -0,0 +1,281 @@
+$(function() {
+
+    $(".fancybox").fancybox();
+    $('.font-up a').click(function(){
+        var taille_police=parseFloat($('.content').css('font-size'),100)+2;
+        if(taille_police<30){
+            var taille_ligne=parseFloat($('.content').css('line-height'),100)+2;
+            $('.content').css({
+                'line-height':taille_ligne+'px',
+                'font-size':taille_police+'px'
+            });
+        }
+        return false;
+    });
+    $('.font-down a').click(function(){
+        var taille_police=parseFloat($('.content').css('font-size'),100)-2;
+        if(taille_police>11){
+            var taille_ligne=parseFloat($('.content').css('line-height'),100)-2;
+            $('.content').css({
+                'line-height':taille_ligne+'px',
+                'font-size':taille_police+'px'
+            });
+        }
+        return false;
+    });
+    
+    /* ANNOTATION HANDLING */
+    
+    var basenode = $(".content")[0],
+        cleanHtml = cleanTextNodes(basenode).innerHtml,
+        textinfo = parseContents(basenode);
+        
+    window.annotations = window.annotations || [];
+    
+    var colors = ["#ff8", "#f88", "#8f8", "#8ff", "#f8f", "#88f"],
+        currentVisibleFrame = null,
+        ncol = 0,
+        mousedown = false,
+        dragging = false;
+    
+    function cleanText(txt, keepbefore, keepafter) {
+        var res = txt.replace(/[\n\r\t]+/gm,' ').replace(/ {2,}/g,' ');
+        if (!keepbefore) {
+            res = res.replace(/^ +/,'');
+        }
+        if (!keepafter) {
+            res = res.replace(/ +$/,'');
+        }
+        return res;
+    }
+    
+    function recursiveParse(node, info) {
+        var children = node.childNodes;
+        for (var i = 0, l = children.length; i < l; i++) {
+            var childnode = children[i];
+            switch(childnode.nodeType) {
+                case node.ELEMENT_NODE:
+                    recursiveParse(childnode, info);
+                break;
+                case node.TEXT_NODE:
+                    var startpos = info.text.length;
+                    info.text += childnode.textContent;
+                    var endpos = info.text.length,
+                        nodeinfo = {
+                            start: startpos,
+                            end: endpos,
+                            length: endpos - startpos,
+                            textNode: childnode
+                        };
+                    childnode._nodeInfo = nodeinfo;
+                    info.nodes.push(nodeinfo);
+                break;
+            }
+        }
+    }
+    
+    
+    function parseContents(node) {
+        var res = {
+            text: '',
+            nodes: []
+        };
+        recursiveParse(node, res);
+        return res;
+    }
+    
+    function cleanTextNodes(node) {
+        var children = node.childNodes;
+        for (var i = 0, l = children.length; i < l; i++) {
+            var childnode = children[i];
+            switch(childnode.nodeType) {
+                case node.ELEMENT_NODE:
+                    cleanTextNodes(childnode);
+                break;
+                case node.TEXT_NODE:
+                    var keepbefore = (i && children[i-1].nodeType == node.ELEMENT_NODE),
+                        keepafter = (i < l-1 && children[i+1].nodeType == node.ELEMENT_NODE);
+                    childnode.textContent = cleanText(childnode.textContent, keepbefore, keepafter);
+                break;
+            }
+        }
+        return node;
+    }
+    
+    function highlightText(start, end, color) {
+        var annotation = {
+            startOffset: start,
+            endOffset: end,
+            color: color,
+            comment: "",
+            annotatedText: textinfo.text.substring(start, end),
+            beforeText: textinfo.text.substring(start - 40, start).replace(/^[\S]*\s+/,''),
+            afterText: textinfo.text.substring(end, end + 40).replace(/\s+[\S]*$/,'')
+        }
+        annotations.push(annotation);
+        showAnnotation(annotation);
+    }
+    
+    var frameTpl = _.template(
+        '<div class="annotation-frame" style="border-color: <%- annotation.color %>; top: <%-top %>px; left: <%- left %>px;">'
+        + '<div class="annotation-area" style="background-color: <%- annotation.color %>; height: <%- height %>px;"></div>'
+        + '<form class="annotation-form"><h3>Annoter&nbsp;:</h3>'
+        + '<textarea class="annotation-textarea" placeholder="Mon commentaire&hellip;"><%- annotation.comment || "" %></textarea>'
+        + '</form></div>'
+    );
+    
+    var liTpl = _.template(
+        '<li style="border-color: <%- annotation.color %>;"><h3>Texte annoté</h3>'
+        + '<p class="annotation-text"><%- annotation.beforeText %><b><%- annotation.annotatedText %></b><%- annotation.afterText %></p>'
+        + '<h3>Commentaire</h3><p class="annotation-comment"><%- annotation.comment || "(Sans commentaire)" %></p>'
+    );
+    
+    function showFrameBox() {
+        if (currentVisibleFrame) {
+            $(".annotation-frame-box").show();
+            var offset = currentVisibleFrame.offset(),
+                width = currentVisibleFrame.outerWidth(),
+                height = currentVisibleFrame.outerHeight();
+            $(".annotation-fb-top").css({
+                height: offset.top - 77
+            });
+            $(".annotation-fb-left").css({
+                top: offset.top,
+                height: height,
+                width: offset.left
+            });
+            $(".annotation-fb-right").css({
+                top: offset.top,
+                height: height,
+                left: offset.left + width
+            });
+            var fbbtop = offset.top + height;
+            $(".annotation-fb-bottom").css({
+                top: fbbtop,
+                height: ($("body").height() - fbbtop)
+            });
+        } else {
+            $(".annotation-frame-box").hide();
+        }
+    }
+    
+    function hideAllFrames() {
+        if (currentVisibleFrame) {
+            currentVisibleFrame.hide();
+        }
+        
+        currentVisibleFrame = null;
+        showFrameBox();
+        $(".annotations-list li").removeClass("selected");
+    }
+    
+    function showAnnotation(annotation) {
+        var start = annotation.startOffset,
+            end = annotation.endOffset,
+            color = annotation.color;
+        var spans = [];
+        
+        for (var i = 0, l = textinfo.nodes.length; i < l; i++) {
+            var nodeinfo = textinfo.nodes[i];
+            if (nodeinfo.end > start && nodeinfo.start <= end) {
+                var r = document.createRange(),
+                    s = document.createElement('span'),
+                    rangestart = Math.max(0, start - nodeinfo.start),
+                    rangeend = Math.min(nodeinfo.length, end - nodeinfo.start);
+                s.style.backgroundColor = color;
+                r.setStart(nodeinfo.textNode, rangestart);
+                r.setEnd(nodeinfo.textNode, rangeend);
+                r.surroundContents(s);
+                spans.push(s);
+            }
+        }
+        textinfo = parseContents(basenode);
+        var top = Math.min.apply(Math, spans.map(function(s) { return s.offsetTop })),
+            height = Math.max.apply(Math, spans.map(function(s) { return s.offsetHeight + s.offsetTop })) - top,
+            frame = $(frameTpl({
+                annotation: annotation,
+                top: top,
+                height: height,
+                left: basenode.offsetLeft
+            })),
+            li = $(liTpl({
+                annotation: annotation
+            }));
+        
+        $(".annotation-frames").append(frame);
+        $(".annotation-list").append(li);
+        
+        frame.find(".annotation-textarea").on("keyup change", function() {
+            annotation.comment = $(this).val();
+            li.find(".annotation-comment").text(annotation.comment || "(Sans commentaire)");
+        });
+        
+        var show = function() {
+            if (mousedown) {
+                return;
+            }
+            currentVisibleFrame = frame;
+            frame.show();
+            showFrameBox();
+            li.addClass("selected");
+        }
+        
+        $(spans).hover(show, hideAllFrames);
+        frame.hover(show, hideAllFrames);
+        li.hover(
+            function() {
+                $(spans).addClass("annotation-selected");
+                li.addClass("selected");
+            },
+            function() {
+                $(spans).removeClass("annotation-selected");
+                li.removeClass("selected");
+            }
+        ).click(function() {
+            show();
+            $(window).scrollTop(currentVisibleFrame.offset().top - 100);
+        });
+    }
+    
+    window.annotations.forEach(function(annotation) {
+        showAnnotation(annotation);
+    });
+    
+    $(".content")
+        .mousedown(function() {
+            mousedown = true;
+            dragging = false;
+        })
+        .mousemove(function() {
+            if (mousedown) {
+                dragging = true;
+            }
+        })
+        .mouseup(function() {
+            if (!dragging) {
+                return;
+            }
+            var range = document.getSelection().getRangeAt(0);
+            if (!range.collapsed && range.startContainer._nodeInfo && range.endContainer._nodeInfo) {
+                var start = range.startOffset + range.startContainer._nodeInfo.start,
+                    end = range.endOffset + range.endContainer._nodeInfo.start;
+                highlightText(start, end, colors[ncol++ % colors.length]);
+                document.getSelection().removeAllRanges();
+            }
+        });
+        
+    $(window).mouseup(function() {
+        mousedown = false;
+        dragging = false;
+    });
+    
+    $(".annotation-frame-box").click(hideAllFrames);
+    
+    $(window).resize(function() {
+        showFrameBox();
+        $(".annotation-frame").css({
+            left: basenode.offsetLeft
+        })
+    })
+
+});