Snippets/Cross-wiki editing with CORS

How to use Snippets
List of Snippets
Cross-wiki editing with CORS
Language(s): JavaScript
Compatible with: unknown

Description

edit

Edit a page on a foreign wiki. Could easily be modified for other types of actions.

Code

edit
/**
 * CORS cross-site editing example
 */
function editForeignPage(info) {
    // Custom hooks for edit success / failure (e.g., console.log)
    var errorHook = typeof info.error === 'function', // has error function?
        successHook = typeof info.success === 'function'; // has success hook?

    // Most "modern" browsers except IE support CORS
    if (!$.support.cors) {
        info.error('Your browser does not support CORS! Try Firefox.', 'cors');
        return;
    }

    // Get the foreign edit token
    $.ajax({
        url: info.url, // e.g. "//ru.wikipedia.org/w/api.php"
        dataType: 'json',
        data: {
            action: 'tokens',
            type: 'edit',
            format: 'json',
            origin: location.origin
        },
        success: function (data) { // if we get the token
            var params;
            // Handle various possible errors (possibly not needed)
            if (!(data && data.tokens && data.tokens.edittoken) && errorHook) {
                info.error(data, 'token');
                return;
            }

            params = {
                format: 'json',
                action: 'edit',
                title: info.title,
                summary: info.summary,
                origin: location.origin,
                assert: 'user', // must be logged in!
                token: data.tokens.edittoken
            };
            params[info.editaction] = info.text;
            $.ajax({
                url: info.url,
                type: 'POST',
                dataType: 'json',
                data: params,
                xhrFields: { // CORS XHR magic
                    withCredentials: true
                }
            })
                .done(function (data) {
                    // Success! Run the success function passed in ``info''
                    if (data && data.edit && data.edit.result && data.edit.result === 'Success' && successHook) {
                        info.success(data);
                    } else if (errorHook) { // error, so run error hook
                        info.error(data, 'edit');
                    }
                })
                .fail(function () { // other failure
                    if (errorHook) {
                        info.error(null, 'other');
                    }
                });
        },
        xhrFields: { // CORS XHR magic
            withCredentials: true
        }
    });
}

Examples

edit
// Example
editForeignPage({
    url: '//meta.wikimedia.org/w/api.php',
    title: 'Meta:Sandbox',
    summary: 'Testing cross-site editing using CORS',
    editaction: 'appendtext', // or prependtext, text (replace)
    text: '\nThis is a test.',
    success: function (data) {
        var diff = encodeURIComponent(data.edit.newrevid),
            cont = confirm('Your edit was successful! OK to view diff'),
            protocol = location.href.split('//')[0];
        if (cont) {
            location.href = protocol + '//meta.wikimedia.org/?diff=' + diff;
        }
    },
    error: function (data, errortype) {
        alert('An error occurred! Type: ' + errortype + '; details: ' + data);
        console.error(data);
    }
});

// Interactive test

var hostname = prompt('Full domain name', 'meta.wikimedia.org');
editForeignPage({
    url: '//' + hostname + '/w/api.php', // works on all WMF wikis
    title: prompt('Enter foreign page name', 'Meta:Sandbox'),
    summary: prompt('Enter summary', 'Testing cross-site editing using CORS'),
    editaction: 'appendtext', // or prependtext, text (replace)
    text: '\n' + prompt('Text to append', 'This is a test.'),
    success: function (data) {
        var diff = encodeURIComponent(data.edit.newrevid),
            cont = confirm('Your edit was successful! OK to view diff'),
            protocol = location.href.split('//')[0];
        if (cont) {
            location.href = protocol + '//' + hostname + '/?diff=' + diff;
        }
    },
    error: function (data, errortype) {
        alert('An error occurred! Type: ' + errortype + '; details: ' + data);
    }
});

Notes

edit

See Manual:CORS.