13

I wrote a small user script for adding some buttons to the question editor. The idea came up a few times on Meta Stack Overflow and Stack Overflow, and I just wanted to share a rough version to get the ball rolling. It's quite incomplete, and please don't laugh about the coding approaches.

Also I'm not sure if it's necessary to disguise postings as questions here on Stack Apps. I guess not. But I would have a couple of questions anyway.. ;]

Screenshot

Enter image description here

About

Small user script (.user.js) that adds a few manual buttons. After selecting a word in the answer, the buttons can be used to transform it into a formatted documentation URL. The script tries to deduce the appropriate manual from the tags of the original question. Thus it will not currently work on reediting an answer.

License

Public Domain (free reuse, no attribution required)

Code

I'm "hosting" this in the answer below for now. Once there is a usable version, it will certainly be moved onto user scripts, etc. for easier download. I'm requesting my laziness is excused.

Platform

Only tested with Opera for now.


Current Issues

  1. Is there some documentation here for using the WMD functions? I would prefer to use the native .getSelection(), for example, rather than bundling a jq.fn.getSelection plugin (half the code, see below).

  2. Which event would you have to trigger for WMD to update the preview? I tried .change and .keyup to no effect.

  3. Do you want to contribute another documentation resource to add? Preferably where you can likewise add simplistic 1:1 function name-to-URL mappings.

6
  • 1
    You shouldn't have to include jQuery on userscripts as all the stackexchange use jQuery already.
    – Jonathan.
    Mar 21, 2011 at 21:41
  • @Jonathan. No, my formulation was misleading. I was talking about an jquery extension plugin. I'm not bundling jquery itself. (I'm quite happy that it's sort of used per default almost everywhere ;)
    – mario
    Mar 21, 2011 at 22:31
  • @mario, right of course :) Great extension now that I can see the screenshot :)
    – Jonathan.
    Mar 21, 2011 at 22:40
  • It's not necessary to disguise postings as questions here. Releases of apps and scripts are a special case. See How do I list my app here? and some other postings for information and models. Mar 22, 2011 at 2:02
  • @mario how can I install it on Firefox 4? I've tried creating manually a UserScript in Greasemonkey and pasting the code, but doesn't seem to be working... :/ Apr 29, 2011 at 15:28
  • @Oscar: Just tested: It doesn't work in FF4. No idea why. Only used it with Opera. I'll have to investigate this. But it has no C# documentation shortcuts yet anyway.
    – mario
    Apr 29, 2011 at 16:26

1 Answer 1

2
// Provide quick documentation links in Stackoverflow editor
//
// ==UserScript==
// @name           SO doc shortcuts+
// @description    Adds extra buttons to turn selected text into online manual links
// @version        0.2
// @namespace      data:,00000000000000000000000000000000e3272d8553c99672fa541449b491dd05
// @include        http*://*stackexchange.com/*
// @include        http*://*stackoverflow.com/*
// ###@include        http://*superuser.com/*
// ###@include        http://*serverfault.com/*
// ###@include        http://*doctype.com/*
// ###@include        http://*askubuntu.com/*
// ==/UserScript==

(function(){

    // configured online manuals and functionname->link rewrite code
    manual_links = {

        php: {
            always: 0,
            icon: "https://static.php.net/www.php.net/favicon.ico",
            raw: 0,
            rewrite: function (text) {
                return "http://php.net/" + encodeURI(text);
            }
        },
        javascript: {
            icon: "http://developer.mozilla.org/favicon.ico",
            rewrite: function (text) {
                return "https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/" + encodeURI(text);
                //return "http://www.w3schools.com/ಠ_ಠ/"+text;
            }
        },
        jquery: {
            icon: "http://static.jquery.com/favicon.ico",
            rewrite: function (text) {
                text = text.replace(/^[$]?[.]/, "jQuery.");
                text = text.replace(/[.]/, "");
                var map = { "ajax":"jQuery.ajax", "browser":"jQuery.browser", "contains":"jQuery.contains" };
                text = map[text] ? map[text] : text;
                return "http://api.jquery.com/" + encodeURI(text) + "/";
            }
        },
        mysql: {
            icon: "http://dev.mysql.com/common/themes/sakila/favicon.ico",
            rewrite: function (text) {
                return "http://search.mysql.com/search/query/search?group=refman-55&q=" + text;
            }
        },
        wordpress: {
            icon: "http://codex.wordpress.org/favicon.ico",
            rewrite: function (text) { return "http://codex.wordpress.org/Function_Reference/"+text; }
        },
        google: {
            always: 1,
            icon: "https://www.google.com/favicon.ico",
            raw: 1,
            rewrite: function (text) {
                return "http://www.google.com/search?q=" + encodeURI(text);
            }
        },
        magic_service_yet_to_be_created: {
            always: 0,
            icon: "https://cdn.sstatic.net/Sites/stackoverflow/img/favicon.ico",
            raw: 1,
            rewrite: function (text) {
                var wait = 0;
                $.ajax({
                     url: "http://magic/get_manual_links",
                     data: {q:text},
                     dataType: "html",
                     success: function (data) { wait=data; },
                     async: false
                });
                return wait;
            }
        }

    };


    // collect current tags
    var question_tags = {};
    $(".post-taglist .post-tag[rel=tag]").each(function(i){ question_tags[this.text]=1; });
 //   alert(question_tags);

    // iterate over configured links
    var pos = 400;   // hacket-y-hack
    for (var i in manual_links) {

        // insert button
        if (manual_links[i].always || question_tags[i]) {

            var html = $('<li class="wmd-button" '+
              'style="z-index:20; left:'+(pos+=25)+'px" '+
              'onClick="document.wmd_doc_link(\''+i+'\')" title="'+i+' manual link">'+
              '<img src="'+ manual_links[i].icon +'" width=16 height=16>'+
              '</li>'
             );
           $("#wmd-button-bar").prepend(html);
            //.insertAfter("#wmd-redo-button");
        }
    }
    //alert("adding buttons");


    // button callback
    document.wmd_doc_link = function (tag) {

       // alert("wmd_doc_link");
        // get selection
        var area = $("#wmd-input");
        var text = area.getSelection().text;

        // rewrite
        var link = manual_links[tag].rewrite( !manual_links[tag].raw ? text.replace(/[^-.\w]+/, "") : text, tag );
        // into link
        if (  ! link.match( /\]\(/ )   ) {
            link = "[`" + text + "`](" + link + ")";
        }

        // update textarea
        area.replaceSelection(link);
        area.change();  // Damn you WMD, why you ignore that?!
        area.trigger('keyup');
    };





/*
 * jQuery plugin: fieldSelection - v0.1.0 - last change: 2006-12-16
 * (c) 2006 Alex Brem <[email protected]> - http://blog.0xab.cd
 */
    var fieldSelection = {
            getSelection: function() {
                    var e = this.jquery ? this[0] : this;
                    return (
                            /* mozilla / dom 3.0 */
                            ('selectionStart' in e && function() {
                                    var l = e.selectionEnd - e.selectionStart;
                                    return { start: e.selectionStart, end: e.selectionEnd, length: l, text: e.value.substr(e.selectionStart, l) };
                            }) ||
                            /* exploder */
                            (document.selection && function() {
                                    e.focus();
                                    var r = document.selection.createRange();
                                    if (r == null) {
                                            return { start: 0, end: e.value.length, length: 0 };
                                    }
                                    var re = e.createTextRange();
                                    var rc = re.duplicate();
                                    re.moveToBookmark(r.getBookmark());
                                    rc.setEndPoint('EndToStart', re);
                                    return { start: rc.text.length, end: rc.text.length + r.text.length, length: r.text.length, text: r.text };
                            }) ||
                            /* browser not supported */
                            function() {
                                    return { start: 0, end: e.value.length, length: 0 };
                            }
                    )();
            },
            replaceSelection: function() {
                    var e = this.jquery ? this[0] : this;
                    var text = arguments[0] || '';
                    return (
                            /* mozilla / dom 3.0 */
                            ('selectionStart' in e && function() {
                                    e.value = e.value.substr(0, e.selectionStart) + text + e.value.substr(e.selectionEnd, e.value.length);
                                    return this;
                            }) ||
                            /* exploder */
                            (document.selection && function() {
                                    e.focus();
                                    document.selection.createRange().text = text;
                                    return this;
                            }) ||
                            /* browser not supported */
                            function() {
                                    e.value += text;
                                    return this;
                            }
                    )();
            }
    };
    jQuery.each(fieldSelection, function(i) { jQuery.fn[i] = this; });
/*
 * jQuery plugin: fieldSelection - v0.1.0 - last change: 2006-12-16
 * (c) 2006 Alex Brem <[email protected]> - http://blog.0xab.cd
 */



})();
1
  • This did not do anything for me (FF 12.0, Ubuntu 12.04, Greasemonkey). Maybe the script gets loaded to early and the form isn't there yet. It's also added dynamically after all. I took some code from it and hacked something together for my needs: User script for CTAN Package and TeXDoc.net buttons May 9, 2012 at 19:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .