Take the 2-minute tour ×
Stack Apps is a question and answer site for apps, scripts, and development with the Stack Exchange API. It's 100% free, no registration required.

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.

share|improve this question
1  
You shouldn't have to include jQuery on userscripts as all the stackexchange use jQuery already. –  Jonathan. Mar 21 '11 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 '11 at 22:31
    
@mario, right of course :) Great extension now that I can see the screenshot :) –  Jonathan. Mar 21 '11 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. –  Dennis Williamson Mar 22 '11 at 2:02
1  
+1 User-configurable doc sources would be great! –  Dennis Williamson Mar 22 '11 at 2:03
    
@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... :/ –  Oscar Mederos Apr 29 '11 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 '11 at 16:26
1  
+1 We really need this on TeX.SE for LaTeX packages on CTAN! –  Martin Scharrer May 9 '12 at 7:13
    
This post could be improved by listing the supported languages and the sites the link to, rather than making me dig around in the code to see that you don't support my favorite languages. –  dmckee May 3 '13 at 21:47
add comment

2 Answers 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.1
// @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: "http://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: "http://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: "http://sstatic.net/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 });

    // 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]) {

            $('<li class="wmd-button" '+
              'style="left:'+(pos+=25)+'px" '+
              'onclick="wmd_doc_link(\''+i+'\')" title="'+i+' manual link">'+
              '<img src="'+ manual_links[i].icon +'">'+
              '</li>'
             ).insertAfter("#wmd-link-button");
        }
    }


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

        // 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 <alex@0xab.cd> - 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 <alex@0xab.cd> - http://blog.0xab.cd
 */



})();
share|improve this answer
    
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 –  Martin Scharrer May 9 '12 at 19:34
add comment

You must log in to answer this question.

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