Mefiquote

By Plutor Last update May 29, 2009 — Installed 1,748 times. Daily Installs: 0, 2, 2, 0, 1, 0, 1, 0, 1, 0, 1, 0, 3, 3, 2, 1, 0, 1, 1, 0, 2, 2, 1, 0, 1, 4, 3, 3, 0, 2, 4, 1

There are 5 previous versions of this script.

// ==UserScript==
// @name           Mefiquote
// @namespace      http://plutor.org/
// @description    Adds "quote" links to Metafilter comments.
// @include        http://metafilter.com/*
// @include        http://*.metafilter.com/*
// @require        http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js
// // ==/UserScript==
//
// DONE 2009-05-29
//
// TODO
// * Play nice with MeFi Navigator
// * Make it work with epiphany and opera
// * Check the highlight to make sure it's part of the clicked comment
// * Ability to link to the original post on preview

var BUTTONTEXT = 'quote';
var QUOTEFORMAT = '<a href="%l">%n</a>: "<i>%q</i>"';

/* ======================================================================== */

function mq_quotethis(evt) {
    var commenttextarea = $("#comment");
    if (commenttextarea.length < 1) return;

    var quotelink = $(this);
    var metadata = quotelink.parent();
    var comment = metadata.parent();

    // Get all of the data to fill in placeholders
    var quotebits = new Object;
    quotebits['%'] = '%';

    if ( document.getSelection().toString() != "" ) {
        quotebits.q = document.getSelection().toString();
    } else {
        quotebits.q = new String(comment.html());
        quotebits.q = quotebits.q.replace(/<br>/ig, '');
        // Remove the trailing metadata
        quotebits.q = quotebits.q.slice(0,
                            quotebits.q.lastIndexOf('<span class="smallcopy">posted by'));
        // Remove the player from music
        quotebits.q = quotebits.q.slice(0,
                            quotebits.q.lastIndexOf('<object '));
        // Remove the more inside junk
        quotebits.q = quotebits.q.replace(/<\/?div[^>]*>/g, '');
        quotebits.q = quotebits.q.replace(/^[ \t\n]*/, '');
        quotebits.q = quotebits.q.replace(/[ \t\n]*$/, '');
    }

    // Default to top of the thread, just in case
    quotebits.l = "" + location.protocol + "//" + location.host + location.pathname;

    // The rest of the data
    metadata.children('a').each( function(i) {
        var url = $(this).attr('href');
        var path = url.replace(/https?:\/\/([^\/]*\.)?metafilter.com/, '');
        if (url == path && path.match('^/'))
            url = "" + location.protocol + "//" + location.host + path;

        if (path.match(/^\/user\/(\d+)/)) {
            quotebits.i = RegExp.$1;
            quotebits.n = $(this).html();
            quotebits.n = quotebits.n.replace(/<.*/, '');
            quotebits.p = url;
        } else if (path.match(/#\d+$/)) {
            quotebits.l = url;
        }
    } );

    // Replace all of the placeholders
    var quoteregex = new RegExp('%(.)', 'g');
    var quotehtml = new String();
    var lastIndex = 0;
    while ( quoteregex.exec(QUOTEFORMAT) ) {
        var thisIndex = quoteregex.lastIndex;
        quotehtml = quotehtml.concat( QUOTEFORMAT.substr(lastIndex, thisIndex-lastIndex-2) );
        var val = quotebits[QUOTEFORMAT.substr(thisIndex-1, 1)];
        if (val != undefined) {
            quotehtml = quotehtml.concat( quotebits[QUOTEFORMAT.substr(thisIndex-1, 1)] );
        } else {
            quotehtml = quotehtml.concat( '%' + QUOTEFORMAT.substr(thisIndex-1, 1) );
        }

        lastIndex = thisIndex;
    }
    quotehtml = quotehtml.concat( QUOTEFORMAT.substr(lastIndex) );

    // GM_log( quotehtml );
    var commentval = commenttextarea.val() || "";
    if (commentval != "" && !commentval.match(/\n\n$/)) {
        commentval += "\n\n";
    }
    commentval += quotehtml + "\n\n";

    commenttextarea.val(commentval);
}

/* ======================================================================== */

function mq_load_preferences() {
    BUTTONTEXT = GM_getValue('mefiquote_buttontext', BUTTONTEXT);
    QUOTEFORMAT = GM_getValue('mefiquote_quoteformat', QUOTEFORMAT);
}

function mq_save_preferences() {
    var buttontext_el = $('#mq_buttontext');
    var quoteformat_el = $('#mq_quoteformat');
    GM_setValue('mefiquote_buttontext', buttontext_el.val() || BUTTONTEXT);
    GM_setValue('mefiquote_quoteformat', quoteformat_el.val() || QUOTEFORMAT);

    return true; /* So it actually submits, too */
}

/* ======================================================================== */

function mq_escape(str) {
    return str.replace(/"/g, '&quot;');
}

/* ======================================================================== */

function mq_init_preferences() {
    var inputs = $('input');
    var submit_button = $('input[type=submit]').filter( function() {
        return $(this).val().match(/Save your Preferences/);
    } );
    if (inputs.length < 1 || submit_button.length < 1) return;

    // Create the fieldset
    var mefiquote_fieldset = $('<fieldset>'
            + '<legend>MefiQuote preferences</legend>'
            + '<label for="mq_buttontext">Quote button text: </label>'
            + '<input type="text" id="mq_buttontext" name="mq_buttontext" value="'
            + mq_escape(BUTTONTEXT)
            + '" maxlength="200" size="30" onfocus="this.style.background=\'#ddd\';" onblur="this.style.background=\'#ccc\';" /><br />'
            + '<label for="mq_quoteformat">Quote format:<br />'
            + '<span class="smallcopy" style="text-align: left">%i - commenter\'s user id<br />%l - url of comment<br />%n - commenter\'s name<br />%p - url of commenter\'s profile<br />%q - comment text<br />%% - an actual percent ("%")</span></label>'
            + '<textarea name="mq_quoteformat" id="mq_quoteformat" cols="60" rows="8" wrap="VIRTUAL" style="width:400px;height:200px;" onfocus="this.style.background=\'#ddd\';" onblur="this.style.background=\'#ccc\';>'
            + mq_escape(QUOTEFORMAT) 
            + '</textarea>'
            + '</fieldset>')
        .insertBefore(submit_button);

    // Add javascript to the form
    submit_button.parents('form').submit( mq_save_preferences );
}

function mq_init_thread() {
    var commenttextarea = $("#comment");
    if (commenttextarea.length < 1) return;

    var n = 0;
    $('span').each( function(i) {
        var curr = $(this);
        if (curr.hasClass('smallcopy') && curr.html().match(/^posted by/) &&
            curr.parents('#prevDiv2, form').length == 0) {
            // Skip the first (post) quote link on preview
            if (location.pathname.match('^/contribute/post_comment_preview.mefi') && n++ == 0)
                return;

            // Add the button
            var quotebutton = $('<a href="#comment">' + BUTTONTEXT + '</a>')
                .attr('target', '_self')
                .click(mq_quotethis);

            curr.append(' [').append( quotebutton ).append(']');
        }
    } );
}

function mq_init() {
    mq_load_preferences();

    var url = location.pathname;

    if (url.match(/^\/(\d+)/) || url.match('^/contribute/post_comment_preview.mefi')) {
        mq_init_thread();
    } else if (url.match('^/contribute/customize.cfm')) {
        mq_init_preferences();
    }
}

$(mq_init);