// ==UserScript==
// @name          Case Wiki Animate
// @namespace     http://blog.case.edu/jms18/code/greasemonkey/
// @description	  Animates page modifications between two specific edit points
// @include       http://wiki.case.edu/index.php?title=*&action=history*
// ==/UserScript==

(

function() {
    
    document.animate_start = function() {
        
        document.animate_urls = new Array();
        document.animate_pages = new Array();
        document.animate_info = new Array();
        document.animate_pos = 0;
        document.animate_interval = -1;
        document.animate_status = 0;  /* Status codes:
                                         0: history
                                         1: loading
                                         2: playing
                                         3: paused
                                         4: playhead scrub */
        
        var external_links = false;
        
        var history = document.getElementById('pagehistory');
        var items = history.getElementsByTagName('li');
        
        if (document.getElementById('animate_range_all').checked) {
            var last_row = items[items.length - 1];
			
            var links = last_row.getElementsByTagName('a');

            //if (links[1].firstChild.nodeValue == 'last') {
                external_links = true;
                var url = '' + window.location;
                var base_url = url.substr(0, url.indexOf('&'));
                
                var button1 = document.getElementById('animate_button1');
                button1.value = 'Loading...';
                button1.setAttribute('disabled', 'disabled');
                
                var button2 = document.getElementById('animate_button1');
                button2.value = 'Loading...';
                button2.setAttribute('disabled', 'disabled');
                
                var request = new XMLHttpRequest();
                request.open('GET', base_url + '&action=history&limit=5000&offset=0', true);
                request.onreadystatechange = function() {
                    if (request.readyState == 4) {
                        var start = request.responseText.indexOf('<!-- start content -->');
                        var end = request.responseText.indexOf('<!-- end content -->');
                        var content = request.responseText.substr(start, end - start);
                        document.swap_content('bodyContent', content);
                        
                        var history = document.getElementById('pagehistory');
                        var items = history.getElementsByTagName('li');
                        var inputs = items[items.length - 1].getElementsByTagName('input');
                        inputs[0].checked = true;
                        
                        document.animate_load();
                    }
                }
                request.send(null);
            //}
        }
        
        if (!external_links) {
            document.animate_load();
        }
    }
    
    document.animate_load = function() {
        
        var history = document.getElementById('pagehistory');
        var skip_minor = document.getElementById('animate_skip_minor');
        var items = history.getElementsByTagName('li');
        var found_start = false;
        var urls = document.animate_urls;
        var info = document.animate_info;
        
        for (var i = 0; i < items.length; i++) {
            var radios = items[i].getElementsByTagName('input');
            if (skip_minor.checked == true) {
                var spans = items[i].getElementsByTagName('span');
                var skip = false;
                for (var j = 0; j < spans.length; j++) {
                    if (spans[j].className == 'minor') {
                        skip = true;
                    }
                }
                if (skip) {
                    continue;
                }
            }
            
            if (radios[1] && radios[1].checked) {
                var links = items[i].getElementsByTagName('a');
                if (links[0].firstChild.nodeValue != 'cur') {
                    urls.unshift(links[1].getAttribute('href'));
                    info.unshift(document.animate_parse_info(items[i], 1));
                } else {
                    urls.unshift(links[2].getAttribute('href'));
                    info.unshift(document.animate_parse_info(items[i], 2));
                }
                found_start = true;
            } else if (radios[0] && radios[0].checked) {
                var links = items[i].getElementsByTagName('a');
                if (links[1].firstChild.nodeValue != 'last') {
                    urls.unshift(links[1].getAttribute('href'));
                    info.unshift(document.animate_parse_info(items[i], 1));
                } else {
                    urls.unshift(links[2].getAttribute('href'));
                    info.unshift(document.animate_parse_info(items[i], 2));
                }
                break;
            } else if (found_start) {
                var links = items[i].getElementsByTagName('a');
                urls.unshift(links[2].getAttribute('href'));
                info.unshift(document.animate_parse_info(items[i], 2));
            }
        }
        
        var history_nav = document.getElementById('ca-history');
        history_nav.className = '';
        /*history_nav.getElementsByTagName('a').item(0).onclick = function() {
            document.animate_status = 0;
            document.swap_content('bodyContent', document.history_content);
            histrowinit();
            this.parentNode.className = 'selected';
            this.parentNode.parentNode.removeChild(document.animate_nav);
            document.getElementById('animate_button1').onclick = document.animate_start;
            document.getElementById('animate_button2').onclick = document.animate_start;
            return false;
        }*/
        
        var animate_nav = document.createElement('li');
        document.animate_nav = animate_nav;
        var link = animate_nav.appendChild(document.createElement('a'));
        link.appendChild(document.createTextNode('animate'));
        link.setAttribute('href', '#');
        link.onclick = function() {
            return false;
        }
        animate_nav.className = 'selected';
        history_nav.parentNode.appendChild(animate_nav);
        
        var bodyContent = document.getElementById('bodyContent');
        var start = bodyContent.innerHTML.indexOf('<!-- start content -->');
        var end = bodyContent.innerHTML.indexOf('<!-- end content -->');
        document.history_content = bodyContent.innerHTML.substr(start, end - start);
        
        var animate = '<input type="button" value="Pause" style="float: left; font-size: 10px; margin-top: 5px; width: 50px;" onclick="document.animate_pause();" id="animate_control"/> ' +
                      '<div id="animate_scrubber" style="position: relative; width: 402px; height: 11px; border: 1px solid #AAA; background: #F5F5F5; float: left; margin: 8px;">' +
                      '<div id="animate_load_progress" style="position: absolute; top: 1px; left: 1px; background: #E1E1E1; height: 9px; width: 5px; visibility: hidden;"></div>' +
                      '<div id="animate_playhead" style="position: absolute; left: 1px; top: 1px; cursor: pointer; background: transparent url(data:image/gif;base64,R0lGODlhCQAJAIAAAP///wAAACH5BAEAAAAALAAAAAAJAAkAAAIRhBGnwYrcDJxvwkplPtchVQAAOw==) no-repeat; height: 9px; width: 9px;"></div></div>' +
                      '<div id="animate_status" style="font: 10px verdana, sans-serif; float: left; margin-top: 8px;">Loading...</div>' +
                      '<br style="clear: both;"/><div id="animate_info" style="font-size: 10px; margin: 0 0 20px 58px;"></div>' +
                      '<div id="animate_content" style="width: 100%"></div>';
        document.swap_content('bodyContent', animate);
        document.animate_status = 1;
        
        var playhead = document.getElementById('animate_playhead');
        playhead.onmousedown = document.animate_playhead;
        
        var body = document.getElementsByTagName('body').item(0);
        body.onmouseup = document.animate_mouseup;
        body.onmousemove = document.animate_mousemove;
        
        
        var request = new XMLHttpRequest();
        request.num = 0;
        
        request.open('GET', document.animate_urls[0], true);
        request.onreadystatechange = function() {
            if (request.readyState == 4) {
                document.animate_loaded(request, request.responseText);
            }
        }
        request.send(null);
        
    }
    
    document.animate_parse_info = function(item, l) {
        var info = '';
        var links = item.getElementsByTagName('a');
        
        if (document.getElementById('animate_info_date').checked) {
            var href = links.item(l).getAttribute('href');
            var text = links.item(l).firstChild.nodeValue;
            info += '<a href="' + href + '">' + text + '</a> ';
        }
        if (document.getElementById('animate_info_author').checked) {
            var href = links.item(l + 1).getAttribute('href');
            var text = links.item(l + 1).firstChild.nodeValue;
            info += 'by <a href="' + href + '">' + text + '</a> ';
        }
        if (document.getElementById('animate_info_summary').checked) {
            var em = item.getElementsByTagName('em');
            if (em.length == 1) {
                info += '&nbsp;&nbsp;&nbsp;' + em.item(0).innerHTML;
            }
        }
        
        return info;
    }
    
    document.animate_loaded = function(request, content) {
        document.getElementById('animate_status').innerHTML = 'Loaded ' + (request.num + 1) + ' of ' + document.animate_urls.length;
        var start = request.responseText.indexOf('<!-- start content -->');
        var end = request.responseText.indexOf('<!-- end content -->');
        var content = request.responseText.substr(start, end - start);
        document.animate_pages[request.num] = content;
        
        var load_progress = document.getElementById('animate_load_progress');
        load_progress.style.width = 5 + (395 * request.num / (document.animate_urls.length - 1)) + 'px';
        load_progress.style.visibility = 'visible';
        
        if (document.animate_status == 1) {
            document.swap_content('animate_content', content);
            
            var playhead = document.getElementById('animate_playhead');
            playhead.style.left = 1 + (390 * request.num / (document.animate_urls.length - 1)) + 'px';
            
            document.animate_set_info(request.num);
            
            document.animate_pos = request.num;
        }
        
        if (request.num + 1 < document.animate_urls.length &&
            document.animate_status != 0) {
            
            var request_num = request.num + 1;
            
            var request = new XMLHttpRequest();
            request.num = request_num;
            request.open('GET', document.animate_urls[request_num], true);
            request.onreadystatechange = function() {
                if (request.readyState == 4) {
                    document.animate_loaded(request, request.responseText);
                }
            }
            request.send(null);
        } else if (request.num + 1 == document.animate_urls.length) {
            document.animate_pause();
        }
    }
    
    document.animate_play = function() {
        var control = document.getElementById('animate_control');
        control.value = 'Pause';
        control.onclick = document.animate_pause;
        
        if (document.animate_pos + 1 == document.animate_urls.length) {
            var playhead = document.getElementById('animate_playhead');
            playhead.style.left = '1px';
            document.animate_pos = 0;
        }
        document.animate_status = 2;
        document.animate_show_frame();
        var delay = Math.round(parseFloat(document.getElementById('animate_delay').value) * 1000);
        document.animate_interval = setInterval('document.animate_show_frame();', delay);
    }
    
    document.animate_pause = function() {
        var control = document.getElementById('animate_control');
        control.value = 'Play';
        control.onclick = document.animate_play;
        
        if (document.animate_interval != -1) {
            clearInterval(document.animate_interval);
        }
        document.animate_status = 3;
    }
    
    document.animate_show_frame = function(frame) {
        
        if (document.animate_status == 0 ||
            document.animate_status == 3) {
            return;
        } if (document.animate_status != 4) {
            frame = document.animate_pos;
            var playhead = document.getElementById('animate_playhead');
            playhead.style.left = 1+ (390 * frame / (document.animate_urls.length - 1)) + 'px';
        }
        
        document.swap_content('animate_content', document.animate_pages[frame]);
        document.animate_set_info(frame);
        
        if (document.animate_status == 2) {
            if (document.animate_pos + 1 >= document.animate_pages.length) {
                document.animate_pause();
            } else {
                document.animate_pos++;
            }
        }
    }
    
    document.animate_set_info = function(num) {
        document.swap_content('animate_info', document.animate_info[num]);
    }
    
    document.animate_playhead = function(e) {
        document.animate_status = 4;
        return false;
    }
    
    document.animate_mousemove = function(e) {
        if (document.animate_status != 4) {
            return;
        }
        
        var scrubber = document.getElementById('animate_scrubber');
        var left = 0;
        var curr = scrubber;
        while (curr.offsetParent) {
            left += curr.offsetLeft;
            curr = curr.offsetParent;
        }
        
        var playhead = document.getElementById('animate_playhead');
        var x = e.pageX - left - 5;
        
        if (x > 391) {
            x = 391;
        } else if (x < 1) {
            x = 1;
        }
        
        var load_progress = document.getElementById('animate_load_progress');
        if (x > parseInt(load_progress.style.width - 5)) {
            x = parseInt(load_progress.style.width - 5);
        }
        
        playhead.style.left = x + 'px';
        
        var snap = Math.round((x - 1) * (document.animate_urls.length - 1) / 390);
        if (snap != document.animate_pos) {
            document.animate_pos = snap;
            document.animate_show_frame(snap);
        }
        
    }
    
    document.animate_mouseup = function(e) {
        if (document.animate_status != 4) {
            return;
        }
        
        var scrubber = document.getElementById('animate_scrubber');
        var left = 0;
        var curr = scrubber;
        while (curr.offsetParent) {
            left += curr.offsetLeft;
            curr = curr.offsetParent;
        }
        
        var playhead = document.getElementById('animate_playhead');
        var x = e.pageX - left - 5;
        
        if (x > 391) {
            x = 391;
        } else if (x < 1) {
            x = 1;
        }
        
        var load_progress = document.getElementById('animate_load_progress');
        if (x > parseInt(load_progress.style.width)) {
            x = parseInt(load_progress.style.width);
        }
        
        var snap = Math.round((x - 1) * (document.animate_urls.length - 1) / 390);
        document.animate_show_frame(snap);
        document.animate_status = 3;
    }
    
    document.swap_content = function(target, content) {
        var target = document.getElementById(target);
        target.innerHTML = content;
    }
    
    var button1 = document.createElement('input');
    button1.style.fontSize = '10px';
    button1.style.cursor = 'pointer';
    button1.setAttribute('type', 'button');
    button1.value = 'Animate changes';
    button1.onclick = document.animate_start;
    button1.setAttribute('id', 'animate_button1');
    
    var button2 = button1.cloneNode(true);
    button2.onclick = document.animate_start;
    button2.setAttribute('id', 'animate_button2');
    
    var history = document.getElementById('pagehistory');
    history.parentNode.insertBefore(button1, history);
    history.parentNode.appendChild(document.createTextNode(' '));
    history.parentNode.appendChild(button2);
    
    var toolbox = document.getElementById('p-tb');
    var options = document.createElement('div');
    options.className = 'portlet';
    options.innerHTML = '<h5>animate options</h5><div class="pBody"><ul>' +
                        '<li>Animate over:' +
                        '<div><input type="radio" name="animate_range" id="animate_range_selected" value="selected" /> Selected</div>' +
                        '<div><input type="radio" name="animate_range" id="animate_range_all" value="all" checked="checked"/> All versions</div>' +
                        '<div><input type="checkbox" id="animate_skip_minor"/> Skip minor edits</div>' +
                        '</li><li>Animate speed:' +
                        '<div>Pause <input type="text" id="animate_delay" value="2.0" size="3" style="font-size: 10px"/> sec</div>' +
                        '</li><li>Include info:' +
                        '<div><input type="checkbox" id="animate_info_date" checked="checked"/> Date/time</div>' +
                        '<div><input type="checkbox" id="animate_info_author" checked="checked"/> Author</div>' +
                        '<div><input type="checkbox" id="animate_info_summary" checked="checked"/> Change summary</div>' +
                        //'<div><input type="radio" name="animate_diff" id="animate_diff_yes" value="yes" checked="checked"/> Yes (cooler)</div>' +
                        //'<div><input type="radio" name="animate_diff" id="animate_diff_no" value="no" checked="checked"/> No (faster)</div>' +
                        '</li></ul></div>';
    toolbox.parentNode.appendChild(options);
        
}

)();

