User:Xover/ocrtoy.js

/* global $, mw */ /* * ocrtoy.js * * This script adds a toolbar button that replaces the editbox text with OCR * text derived by sending the .prp-page-image image through ocrtoy's backend. * */ (function (mw, $) { "use strict";

mw.loader.using(["mediawiki.api", "mediawiki.util", "user.options"], function {    /*     *  First check that this is a context we should be active in.     */

// Only active on Page:-namespace pages. if (mw.config.get('wgCanonicalNamespace') !== 'Page') { return; }

// Only active on pages with content model 'proofread-page'. if (mw.config.get('wgPageContentModel') !== 'proofread-page') { return; }

// Only active when in edit/preview/diff mode. if ($.inArray(mw.config.get('wgAction'), ['edit', 'submit']) < 0) { return; }

/*    * Set up the globals we'll need. */   var sysMessages = [ 'ocrtoy-button-label', 'ocrtoy-request-in-progress', 'ocrtoy-no-text', 'ocrtoy-image-not-found' ];

/*    * Add main UI. Preferences UI is handled by a separate gadget. */   var setupUI; if (mw.user.options.get('usebetatoolbar') === 1) { setupUI = addToolbarButton; // Add button in toolbar if enabled. } else { setupUI = addSidebarLink; // Add a link in the sidebar. }   new mw.Api .loadMessagesIfMissing(sysMessages) .then(setupUI); /*    * Prefetch the OCR results for the current page */   var isInteractive = false; var warmingCache = false; requestOCR(isInteractive, warmingCache);

/*    * Then warm the cache for the next page. */   isInteractive = false; warmingCache = true; requestOCR(isInteractive, warmingCache); }); // END: mw.loader.using

/**  * Add the OCR button to the toolbar. This is called in run, and doesn't  * need to check anything about whether we need to add the button. */ function addToolbarButton { var ocrButtonDetails = { type: 'button', icon: 'https://upload.wikimedia.org/wikipedia/commons/4/48/Ocrtoy_WikiEditor_button.png', label: mw.msg('ocrtoy-button-label'), action: {type: 'callback', execute: doOcr} };   var ocrButton = { section: 'main', group: 'insert', tools: {'ocrtoy': ocrButtonDetails} };   mw.loader.using(['ext.wikiEditor'], function  {      $("#wpTextbox1").wikiEditor('addToToolbar', ocrButton);      $("a[rel='ocrtoy']").css("width", "36px");    }); }

/**  * Add the OCR link to the sidebar. This is called in run, and doesn't  * need to check anything about whether we need to add the link. */ function addSidebarLink { var ocrPortlet = mw.util.addPortletLink(     'p-tb', '#', 'Get OCR', 'ca-ocrtoy',      'Get the OCR for this page from ocrtoy.'    ); $(ocrPortlet).click(function (e) {     e.preventDefault;      doOcr;    }); }

function doOcr { var isInteractive = true; var warmingCache = false; requestOCR(isInteractive, warmingCache); }

function bailOnError(isInteractive, response) { var notifyFunc; if (isInteractive) { notifyFunc = function (m) {console.log(m)}; } else { notifyFunc = function (m) {mw.notify(m)}; }   if (response.responseJSON !== undefined && response.responseJSON.error) { var code   = response.responseJSON.error.code; var message = response.responseJSON.error.message; notifyFunc(mw.msg('error') + ' ' + code + ' ' + message); return true; }   if (response.text === undefined || response.text.length === 0) { notifyFunc(mw.msg('ocrtoy-no-text')); return true; }   return false; }

// Disable or enable the text editor text field and toolbar button function disable_input(disable) { if (disable) { // Install handler for ESC key to abort and re-enable text field and button $(document).keyup(function(e) {if (e.which == 27) {disable_input(false);}});

// Remove click handler from toolbar button. $("a[rel='ocrtoy']").off('click');

// Set HTML form "disabled" property to true. $('#wpTextbox1').prop('disabled', true); } else { // Remove handler for ESC key $(document).off('keyup');

// Add back the click handler on the toolbar button. $("a[rel='ocrtoy']").on('click', doOcr);

// Set HTML form "disabled" property to false. $('#wpTextbox1').prop('disabled', false); } }

/**  * Prefetch the OCR text so it is ready when the user requests it, * or fetch it on demand if it doesn't already exist. * TODO: Make this configurable. */ function requestOCR (isInteractive, warmingCache) { var lang = mw.config.get('wgContentLanguage'); var toolUrl = "https://ocrtoy.wmflabs.org/";

var prefetch = $("#wpTextbox1").data("ocrtoyPrefetch"); if (prefetch !== undefined && isInteractive === true) { $('#wpTextbox1').val(prefetch); console.log("[ocrtoy]: Found data in local cache."); return; }   var notifyFunc; if (isInteractive) { notifyFunc = function (m) {mw.notify(m)}; } else if (warmingCache === true) { notifyFunc = function (m) {return;}; // noop } else { notifyFunc = function (m) {console.log(m)}; }   // Just bail out if the page image can't be found. if ($('.prp-page-image img').length === 0) { notifyFunc(mw.msg('ocrtoy-image-not-found')); }

// Report progress if interactive. if (isInteractive) { disable_input(true); }

var fullsize_width = $('.prp-page-image img').data('fileWidth');

var match = /(.*?)\/(\d+)/.exec(mw.config.get('wgTitle')); var file = match[1]; var page = match[2]; if (warmingCache === true) { page = parseInt(page) + 1; console.log("[ocrtoy]: Going to warm cache for page " + page + "."); }

var getOCR = function (isInteractive, warmingCache, data) { var thumburl = data.query.pages[0].imageinfo[0].thumburl; console.log("ocrtoy thumburl: " + thumburl); var requestUrl = toolUrl + "?image=" + thumburl + "&lang=" + lang; var processOCR = function (isInteractive, warmingCache, response) { if (warmingCache !== true) { var shouldBail = bailOnError(isInteractive, response); if (shouldBail) { return; }       }        if (isInteractive) { console.log("[ocrtoy]: Update text due to interactive request."); $('#wpTextbox1').val(response.text); } else if (warmingCache === true) { console.log("[ocrtoy]: Ignoring returned result whiile warming cache."); return; // Ignore it; we're just warming the server-side cache. } else { console.log("[ocrtoy]: Storing prefetched text for interactive use."); $("#wpTextbox1").data("ocrtoy-prefetch", response.text); }     }.bind(null, isInteractive, warmingCache); $.getJSON(requestUrl) .done(processOCR) .fail(processOCR) // Same handler, for simplicity. .always(function {disable_input(false);}); }.bind(null, isInteractive, warmingCache); // Pass along interactive state

var api = new mw.Api; api.get({     'action': 'query',      'prop': 'imageinfo',      'titles': "File:" + file,      'formatversion': 2,      'format': 'json',      'iiprop': 'url',      'iiurlwidth': fullsize_width,      'iiurlparam': "page" + page + "-" + fullsize_width + "px"    }) .done(getOCR); } }(mediaWiki, jQuery));