User:ערן/spellcheck.js

/** * written by User:ערן basesd on de:MediaWiki:Gadget-Rechtschreibpruefung.js **/ function spellChecker { 'use strict'

var wbSpellCheck = 'Q15098221'; var errors = { installError: ' Please create a dictionary for spelling mistakes and link it to {0} in Wikidata ',       spellListNotFound: 'Page not found: {1}'    }

var mispellsList = localStorage? localStorage.mispellsList : $.cookie( 'mispellsList' ); var dictionary = { misspells: {}, keys: [] }

/*   Setups misspelling gadget - get the site-specific name of page with dictionary. returns $.Deferred */   function setup { var misspellInstall = new $.Deferred; if ( mispellsList ) { misspellInstall.resolve; } else { mw.loader.using('wikibase.api.RepoApi', function{               var repoApi = new wikibase.api.RepoApi                repoApi.getEntities( wbSpellCheck, 'sitelinks').done( function( data ) {

var currSite = mw.config.get( 'wgDBname' ); if ( data.entities && data.entities.hasOwnProperty( wbSpellCheck ) && data.entities[wbSpellCheck].sitelinks && data.entities[wbSpellCheck].sitelinks.hasOwnProperty( currSite ) ) { mispellsList = data.entities[wbSpellCheck].sitelinks[currSite].title; if ( localStorage ) { localStorage.mispellsList = mispellsList; } else { $.cookie( 'mispellsList', mispellsList ); }                       misspellInstall.resolve; } else { mw.notify( $( errors.installError.replace('{0}', wbSpellCheck) ) ); misspellInstall.reject; }               } );            } );        }        return misspellInstall; }

function runSpellCheck { if ( dictionary.keys.length>0 ) { checkSpells( $( '.ve-ce-surface, #mw-content-text:visible' ) ); return; }       $.ajax({            url: mw.config.get('wgServer') + mw.util.wikiScript('index') + '?title=' + mw.util.wikiUrlencode( mispellsList ) + '&action=raw&ctype=text/x-wiki',            dataType: 'html'        }).done( function( dictionaryPage ) {		    //remove intro and headers		    dictionaryPage = dictionaryPage.substr( dictionaryPage.indexOf('==') ).replace( /==.*==/g,'' )		    parseDictionary( dictionaryPage );            checkSpells( $( '.ve-ce-surface, #mw-content-text:visible' ) );	    } ); }

function uniqueArr( listWords ) { var dictWords = {}; var res = []; for ( var i=0; i<listWords.length; i++ ) { dictWords[listWords[i]] = 1; }	   for ( var k in dictWords ) { res.push( k ); }	   return res; }

function extractPageWords( context ) {

var pageWords = {};//unique words in article var wordList = []; var splittedWords = context.text.split(' '); for (var i=0;i<splittedWords.length;i++){ if ( splittedWords[i].length && !( /^[0-9]+$/.test( splittedWords[i] ) ) ) { var trimed = splittedWords[i].replace( /[\[\],\.\(\)]/g, '' ).toLowerCase; pageWords[trimed] = 1; }	   }	    for ( var word in pageWords ) { wordList.push(word); }	   return wordList; }

function parseDictionary( dict ){ //to dictioanry! var correcto = dict.split('\n'); var keyWords = [];

for ( var i=0; i<correcto.length; i++ ){ var entry = correcto[i]; if ( entry.length === 0 || (entry=entry.trim).length === 0 ){ continue;//skip empty lines }		   var fixTriple = entry.split( '|' ); //skip on words appear in title if (!(new RegExp( '\\b' + fixTriple[0] + '\\b','i').test(mw.config.get('wgTitle')))){ dictionary.misspells[fixTriple[0].toLowerCase] = { hint: fixTriple[2], cs: fixTriple[1] == 'cs', //case sensetive word: fixTriple[0] }		       keyWords.push( fixTriple[0].toLowerCase ); }		  	    }        dictionary.keys = uniqueArr( keyWords ); }

function checkSpells( context ) { //extract article words for efficent search var artWords = extractPageWords( context );

var words = dictionary.keys.concat( artWords ); words.sort;

var relevantWords = {}; for (var i = 1; i<words.length; i++){ if ( words[i] == words[i-1] ) { relevantWords[words[i]] = 1; }	   }

for (var k in relevantWords) { markWordStart( context, new RegExp( '\\b' + dictionary.misspells[k].word + '\\b', dictionary.misspells[k].cs? '' : 'i' ), dictionary.misspells[k].hint ); }   }

function markWordStart(context, text, hint) {     var markedElement = context.get(0); if ( markedElement ){ markWord( markedElement, text, hint); }   }    function markWord(node, text, hint) {     var pos, len, newnodes = 0; var newnode, middlenode, endnode; // textnode - search for word if (node.nodeType == 3) {        pos = node.data.search(text); if (pos >= 0) {         // create new span-element newnode = document.createElement("span"); newnode.style.backgroundColor = "#FF9191"; newnode.title = hint; // get length of the matching part len = node.data.match( text )[0].length; // splits content in three parts: begin, middle and end middlenode = node.splitText(pos); endnode = middlenode.splitText(len); // appends a copy of the middle to the new span-node newnode.appendChild(middlenode.cloneNode(true)); // replace middlenode with the new span-node middlenode.parentNode.replaceChild(newnode, middlenode); newnodes = 1; }     }      else if ((node.nodeType == 1)  // element node	       && (node.hasChildNodes) // with child nodes	       && (node.tagName.toLowerCase != "script") // no script, style and form	       && (node.tagName.toLowerCase != "style")	       && (node.tagName.toLowerCase != "form")) {       var this_child; for (this_child = 0; this_child < node.childNodes.length; this_child++) {         this_child = this_child + markWord(node.childNodes[this_child], text, hint); }     }      return newnodes; }

setup.then( runSpellCheck );

mw.hook( 've.activationComplete' ).add( function {       setup.then( function{ // inital find misspells (for all document) runSpellCheck; var doc = ve.instances[0].getView.getDocument; var model = ve.instances[0].getModel; //while editing - only on current node model.on( 'documentUpdate', function {                    var text,	                    selection = model.getSelection,	                    node = doc.getNodeFromOffset( selection.start ),	                    textMatches;                    if ( !( node instanceof ve.ce.ContentBranchNode ) ) {	                    return;                    }                    checkSpells( $( node.$element[0] ) );	                }            ); } );

});

}

$(function{   //run only on active tabs    if ( typeof document.hidden === "undefined" || !document.hidden) spellChecker;    else $(document).one('visibilitychange', spellChecker); });