Benutzer:Schnark/js/veHint.js
Erscheinungsbild
aus Wikipedia, der freien Enzyklopädie
< Benutzer:Schnark | js
Diese Seite enthält Code als JavaScript; siehe auch WP:JS.
Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.
- Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
- Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
- Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
//Dokumentation unter [[Benutzer:Schnark/js/veHint]] <nowiki> /*global mediaWiki, OO, ve*/ (function($,mw){ "use strict"; varl10n={ en:{ 'schnark-ve-problems-total-count':'All problems: 1ドル', 'schnark-ve-problems-find-prev':'Find previous problem', 'schnark-ve-problems-find-next':'Find next problem', 'schnark-ve-problems-replace':'Fix problem', 'schnark-ve-problems-replace-all':'Fix all problems', 'schnark-ve-problems-enable-all':'Enable all problems', 'schnark-ve-problems-disable-all':'Disable all problems', 'schnark-ve-problems-done':'Done', 'schnark-ve-problems-title':'Find problems' }, de:{ 'schnark-ve-problems-total-count':'Alle Probleme: 1ドル', 'schnark-ve-problems-find-prev':'Finde vorheriges Problem', 'schnark-ve-problems-find-next':'Finde nächstes Problem', 'schnark-ve-problems-replace':'Behebe Problem', 'schnark-ve-problems-replace-all':'Behebe alle Probleme', 'schnark-ve-problems-enable-all':'Aktiviere alle Probleme', 'schnark-ve-problems-disable-all':'Deaktiviere alle Probleme', 'schnark-ve-problems-done':'Fertig', 'schnark-ve-problems-title':'Finde Probleme' } },SOURCE=1,VISUAL=2,problemsForProjects={}; functioninitL10N(l10n){ vari,chain=mw.language.getFallbackLanguageChain(); for(i=chain.length-1;i>=0;i--){ if(chain[i]inl10n){ mw.messages.set(l10n[chain[i]]); } } } functionaddToToolbar(tool){ vari,include; try{ include=ve.init.mw.DesktopArticleTarget.static.actionGroups[1].include; i=include.indexOf('findAndReplace'); if(i===-1){ include.push(tool); }else{ include.splice(i+1,0,tool); } }catch(e){ mw.log.warn('veHint.js: addToToolbar failed: '+e); } } functioninit(problems){ //virtual indent varcss= '.schnark-ve-problems-current-problem-highlight {'+ 'background-color: #fc3;'+ '}'+ '.schnark-multicol-layout {'+ 'padding: 0 0.5em;'+ 'max-height: 8em;'+ 'overflow: auto;'+ '}'+ '.schnark-multicol-layout .oo-ui-fieldLayout {'+ 'width: 20em;'+ 'height: 2.5em;'+ 'float: left;'+ '}'; mw.util.addCSS(css); functionMulticolLayout(){ MulticolLayout.parent.apply(this,arguments); this.$element.addClass('schnark-multicol-layout'); this.$group.prepend($('<span>'));//don't remove the margin-top from the first widget } OO.inheritClass(MulticolLayout,OO.ui.FieldsetLayout); functionFindProblemsDialog(){ FindProblemsDialog.parent.apply(this,arguments); } OO.inheritClass(FindProblemsDialog,ve.ui.FindAndReplaceDialog); FindProblemsDialog.static.name='findProblems'; FindProblemsDialog.static.padded=false;//strange issue with padding + overflow //TODO besser lösen, ohne padding sieht es blöd aus FindProblemsDialog.static.problemsVisual=[]; FindProblemsDialog.static.problemsSource=[]; FindProblemsDialog.static.addProblem=function(desc,re,fix,mode){ varproblem={desc:desc,rawRe:re,re:newRegExp('^'+re+'$')}; if(fix!==false){ problem.replace=fix; } if(mode===VISUAL||mode===VISUAL+SOURCE){ FindProblemsDialog.static.problemsVisual.push( $.extend({index:FindProblemsDialog.static.problemsVisual.length},problem) ); } if(mode===SOURCE||mode===VISUAL+SOURCE){ FindProblemsDialog.static.problemsSource.push( $.extend({index:FindProblemsDialog.static.problemsSource.length},problem) ); } }; FindProblemsDialog.prototype.initialize=function(){ varproblemGroup,navigateGroup,replaceGroup,onoffGroup,doneButton,$problemRow,$navRow; ve.ui.FindAndReplaceDialog.parent.prototype.initialize.apply(this,arguments);//eine Hierarchiestufe überspringen this.surface=null; this.invalidRegex=false; this.$findResults=$('<div>').addClass('ve-ui-findAndReplaceDialog-findResults'); this.initialFragment=null; this.startOffset=0; this.fragments=[]; this.results=0; this.renderedResultsCache={}; this.renderedFragments=newve.Range(); this.replacing=false; this.focusedIndex=0; this.query=null; this.problemsForIndexCache=null; if(ve.init.target.getSurface().getMode()==='source'){ this.constructor.static.problems=this.constructor.static.problemsSource; }else{ this.constructor.static.problems=this.constructor.static.problemsVisual; } this.problemSwitches=this.constructor.static.problems.map(function(problem,index){ varid='schnark-ve-problems-problem-'+index, toggleSwitch=newOO.ui.CheckboxInputWidget({ selected:true }),fieldLayout=newOO.ui.FieldLayout(toggleSwitch,{ align:'inline', label:newOO.ui.HtmlSnippet( '<span id="'+id+'">'+problem.desc+'<span class="count"></span></span>' ) }); return{toggleSwitch:toggleSwitch,fieldLayout:fieldLayout}; }); this.previousButton=newOO.ui.ButtonWidget({ icon:'previous', title:ve.msg('schnark-ve-problems-find-prev'), tabIndex:1 }); this.nextButton=newOO.ui.ButtonWidget({ icon:'next', title:ve.msg('schnark-ve-problems-find-next'), tabIndex:1 }); this.replaceButton=newOO.ui.ButtonWidget({ label:ve.msg('schnark-ve-problems-replace'), tabIndex:1 }); this.replaceAllButton=newOO.ui.ButtonWidget({ label:ve.msg('schnark-ve-problems-replace-all'), tabIndex:1 }); this.enableAllButton=newOO.ui.ButtonWidget({ label:ve.msg('schnark-ve-problems-enable-all'), tabIndex:1 }); this.disableAllButton=newOO.ui.ButtonWidget({ label:ve.msg('schnark-ve-problems-disable-all'), tabIndex:1 }); problemGroup=newMulticolLayout({ items:this.problemSwitches.map(function(item){ returnitem.fieldLayout; }), label:newOO.ui.HtmlSnippet( ve.msg('schnark-ve-problems-total-count','<span id="schnark-problems-totalcount">0</span>') ) }); navigateGroup=newOO.ui.ButtonGroupWidget({ classes:['ve-ui-findAndReplaceDialog-cell'], items:[ this.previousButton, this.nextButton ] }); replaceGroup=newOO.ui.ButtonGroupWidget({ classes:['ve-ui-findAndReplaceDialog-cell'], items:[ this.replaceButton, this.replaceAllButton ] }); onoffGroup=newOO.ui.ButtonGroupWidget({ classes:['ve-ui-findAndReplaceDialog-cell'], items:[ this.enableAllButton, this.disableAllButton ] }); doneButton=newOO.ui.ButtonWidget({ classes:['ve-ui-findAndReplaceDialog-cell'], label:ve.msg('schnark-ve-problems-done'), tabIndex:1 }); $problemRow=$('<div>'); $navRow=$('<div>').addClass('ve-ui-findAndReplaceDialog-row').css('padding','0 0.5em'); this.onWindowScrollThrottled=ve.throttle(this.onWindowScroll.bind(this),250); this.updateFragmentsThrottled=ve.throttle(this.updateFragments.bind(this),250); this.renderFragmentsThrottled=ve.throttle(this.renderFragments.bind(this),250); this.problemSwitches.forEach(function(item){ item.toggleSwitch.connect(this,{change:'onProblemsChange'}); },this); this.nextButton.connect(this,{click:'findNext'}); this.previousButton.connect(this,{click:'findPrevious'}); this.replaceButton.connect(this,{click:'onReplaceButtonClick'}); this.replaceAllButton.connect(this,{click:'onReplaceAllButtonClick'}); this.enableAllButton.connect(this,{click:'onEnableAllButtonClick'}); this.disableAllButton.connect(this,{click:'onDisableAllButtonClick'}); doneButton.connect(this,{click:'close'}); this.tabIndexScope=newve.ui.TabIndexScope({ root:this.$element }); this.$content.addClass('ve-ui-findAndReplaceDialog-content'); this.$body .append( $navRow.append(navigateGroup.$element,replaceGroup.$element,onoffGroup.$element,doneButton.$element), $problemRow.append(problemGroup.$element) ); }; FindProblemsDialog.prototype.onProblemsChange=function(){ this.updateFragments(); this.clearRenderedResultsCache(); this.renderFragments(); this.highlightFocused(true); }; FindProblemsDialog.prototype.onEnableAllButtonClick=function(){ this.problemSwitches.forEach(function(item){ item.toggleSwitch.setSelected(true); },this); }; FindProblemsDialog.prototype.onDisableAllButtonClick=function(){ this.problemSwitches.forEach(function(item){ item.toggleSwitch.setSelected(false); },this); }; FindProblemsDialog.prototype.getProblemSelectionStates=function(){ returnthis.problemSwitches.map(function(item){ returnitem.toggleSwitch.isSelected(); }); }; FindProblemsDialog.prototype.updateFragments=function(){ vari,l,startIndex, surfaceModel=this.surface.getModel(), documentModel=surfaceModel.getDocument(), isReadOnly=surfaceModel.isReadOnly(), ranges=[], selectionStates=this.getProblemSelectionStates(), problemCounts,countHtml; this.query=this.constructor.static.problems.filter(function(el,index){ returnselectionStates[index]; }).map(function(problem){ return'(?:'+problem.rawRe+')'; }).join('|'); this.fragments=[]; this.problemsForIndexCache=null; if(this.query){ this.query=newRegExp(this.query,'g'); ranges=documentModel.findText(this.query,{ noOverlaps:true }); for(i=0,l=ranges.length;i<l;i++){ this.fragments.push(surfaceModel.getLinearFragment(ranges[i],true,true)); if(startIndex===undefined&&ranges[i].start>=this.startOffset){ startIndex=this.fragments.length-1; } } } this.results=this.fragments.length; this.focusedIndex=startIndex||0; this.nextButton.setDisabled(!this.results); this.previousButton.setDisabled(!this.results); this.replaceAllButton.setDisabled(!this.results||isReadOnly); problemCounts=this.getCounts(); this.$element.find('#schnark-problems-totalcount').html(this.results); for(i=0;i<problemCounts.length;i++){ if(selectionStates[i]){ countHtml=' ('+problemCounts[i]+')'; }else{ countHtml=''; } this.$element.find('#schnark-ve-problems-problem-'+i+' .count').html(countHtml); } }; FindProblemsDialog.prototype.getCounts=function(){ vari,problemCounts=[]; functionadd(problem){ problemCounts[problem.index]++; } for(i=0;i<this.constructor.static.problems.length;i++){ problemCounts.push(0); } for(i=0;i<this.fragments.length;i++){ this.getProblemsForIndex(i).list.forEach(add); } returnproblemCounts; }; FindProblemsDialog.prototype.createProblemsForIndexCache=function(){ vari; this.problemsForIndexCache=[]; for(i=0;i<this.fragments.length;i++){ this.problemsForIndexCache.push(this.createProblemsForIndex(i)); } }; FindProblemsDialog.prototype.createProblemsForIndex=function(index){ vartext=this.fragments[index].getText(true).replace(/\n/g,'\uFFFC'), selectionStates=this.getProblemSelectionStates(), fixProblem=false, list=this.constructor.static.problems.filter(function(problem,index){ //FIXME teilweise sprechen auch falsche REs an varmatches=selectionStates[index]&&text.search(problem.re)===0; if(text.indexOf('\uFFFC')===-1&&matches&&fixProblem===false&&problem.replace!==undefined){ fixProblem=index; } returnmatches; }); return{list:list,fixProblem:fixProblem}; }; FindProblemsDialog.prototype.getProblemsForIndex=function(index){ if(!this.problemsForIndexCache){ this.createProblemsForIndexCache(); } returnthis.problemsForIndexCache[index]||{list:[],fixProblem:false}; }; FindProblemsDialog.prototype.highlightFocused=function(){ this.findText={setLabel:function(){}}; FindProblemsDialog.parent.prototype.highlightFocused.apply(this,arguments); this.$element.find('.schnark-ve-problems-current-problem-highlight') .removeClass('schnark-ve-problems-current-problem-highlight'); varcurrentProblems=this.getProblemsForIndex(this.focusedIndex); currentProblems.list.forEach(function(problem){ this.$element.find('#schnark-ve-problems-problem-'+problem.index) .addClass('schnark-ve-problems-current-problem-highlight')[0] .scrollIntoView(false); },this); this.replaceButton.setDisabled( currentProblems.fixProblem===false||this.surface.getModel().isReadOnly() ); }; FindProblemsDialog.prototype.findFirst=function(){ varinitialFragment=this.surface.getModel().getFragment(null,true); this.startOffset=ve.getProp( initialFragment.getSelection().getRanges(initialFragment.getDocument()), 0,'start' )||0; this.onProblemsChange(); }; FindProblemsDialog.prototype.focus=function(){}; FindProblemsDialog.prototype.replace=function(index){ varfix=this.getProblemsForIndex(index).fixProblem; if(fix===false){ return; } fix=this.constructor.static.problems[fix]; this.replacing=true; this.fragments[index].insertContent( this.fragments[index].getText().replace(fix.re,fix.replace), true ); setTimeout(function(){ this.replacing=false; }.bind(this)); }; ve.ui.windowFactory.register(FindProblemsDialog); ve.ui.commandRegistry.register( newve.ui.Command( 'findProblems','window','open',{args:['findProblems',null,'findFirst']} ) ); functionFindProblemsTool(){ FindProblemsTool.parent.apply(this,arguments); } OO.inheritClass(FindProblemsTool,ve.ui.FindAndReplaceTool); FindProblemsTool.static.name='findProblems'; FindProblemsTool.static.icon='alert'; FindProblemsTool.static.title=ve.msg('schnark-ve-problems-title'); FindProblemsTool.static.commandName='findProblems'; ve.ui.toolFactory.register(FindProblemsTool); addToToolbar('findProblems'); ve.ui.triggerRegistry.register( 'findProblems',{mac:newve.ui.Trigger('cmd+p'),pc:newve.ui.Trigger('ctrl+p')} ); problems(FindProblemsDialog.static.addProblem); //virtual outdent } problemsForProjects.dewiki=function(add){ functionallowCapital(re){ varfirst=re.charAt(0), firstCapital=first.toUpperCase(); if(first===firstCapital){ returnre; } return'['+first+firstCapital+']'+re.slice(1); } vartypo={//FIXME erweitern 'aberufen':'abgerufen', 'Addresse':'Adresse', 'anderere':'andere', 'andereren':'anderen', 'andererer':'anderer', 'Gallerie':'Galerie', 'Standart':'Standard' },words=[//evt. weitere aus wikilint übernehmen 'bedauerlicherweise', 'bedeutendste', 'bekannte', 'bekannteste', 'berühmteste', 'derzeit', 'einzigste', 'ich', 'in der Regel', 'in den letzten Jahren', 'sogar', 'wichtigste', 'zum Glück', 'zurzeit', 'Insider' ],abbr=[ 'z. B.', 'bzw.', 'd. h.', 'jährl.', 'u. a.', 'hl.', 'engl.', 'ital.', 'span.', 'lat.', 'ca.', 'sog.' ],months=[ 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' ], opening='([„«',closing=')]"»',digitPunct='.,',punct=':;?!',object='\uFFFC'; add('Wortdopplung','\\b(\\S+)\\b(\\W+)\\b\1円\\b','1ドル2ドル',SOURCE+VISUAL); add('Plenk','\\s+(['+mw.util.escapeRegExp(digitPunct+punct+closing+'/')+ '])|(['+mw.util.escapeRegExp(opening+'/')+'])\\s+','1ドル2ドル',SOURCE+VISUAL); add('Klemp', '(['+mw.util.escapeRegExp(punct)+'])([^ '+mw.util.escapeRegExp(closing)+object+'])|'+ '(,)([^ \\d'+mw.util.escapeRegExp(closing)+object+'])|'+ '(\\.)([^ \\-\\da-z'+mw.util.escapeRegExp(closing)+object+'])', '1ドル3ドル5ドル 2ドル4ドル6ドル',VISUAL); add('Mehrfache Leerzeichen',' {2,}',' ',VISUAL); add('Überflüssige Leerzeichen',' +$','',VISUAL+SOURCE); add('Kleinschreibung','([.!?]\\s+)([a-zäöü])',function(all,pre,char){ returnpre+char.toUpperCase(); },SOURCE+VISUAL); add('Tippfehler','\\b(?:'+Object.keys(typo).map(mw.util.escapeRegExp).join('|')+')\\b',function(word){ returntypo[word]; },SOURCE+VISUAL); add('Zahlenformat (4-stellig)','\\b(\\d)\\.(\\d{3})\\b','1ドル2ドル',VISUAL+SOURCE); add('Zahlenformat',' \\d{5,}\\b',function(number){ functiongroup(n){ if(n.length<=3){ returnn; } returngroup(n.slice(0,-3))+'.'+n.slice(-3); } return' '+group(number.slice(1)); },SOURCE+VISUAL); add('Unerwünschte Wörter','\\b(?:'+words.map(mw.util.escapeRegExp).map(allowCapital).join('|')+')\\b', false,SOURCE+VISUAL); add('Abkürzung','\\b(?:'+abbr.map(mw.util.escapeRegExp).map(allowCapital).join('|')+')',false,SOURCE+VISUAL); add('Langer Satz','(?:\\b\\S+\\b[ ,]){50,}',false,SOURCE+VISUAL); add('Datum','\\b([0-3]?[0-9])\\.\\s*([01]?[0-9])\\.\\s*',function(all,day,month){ returnString(Number(day))+'. '+months[Number(month)-1]+' '; },SOURCE+VISUAL); add('Gedankenstrich',' - ',' – ',SOURCE+VISUAL); add('Bis-Strich zwischen Jahren','([^-0-9][12][0-9]{3}) *- *([12][0-9]{3}[^-0-9])','1ドル–2ドル',SOURCE+VISUAL); add('Bis-Strich zwischen Seiten','\\b(Sp?\\.|Seiten?|Spalten?) *(\\d+) *- *','1ドル 2ドル–',SOURCE+VISUAL); add('Bis-Strich mit Leerzeichen','(\\d) +(–) +(\\d)','1ドル2ドル3ドル',SOURCE+VISUAL); add('Auslassungspunkte','\\.\\.\\.','...',SOURCE+VISUAL); add('Anführungszeichen','"([^"\\n]{0,100})"','„1ドル"',VISUAL); add('Apostroph','\'','’',VISUAL); add('Zusammenstoßende Links','\\]\\]\\[\\[',false,SOURCE); add('Weblinks','^\\s*(?:[eE]xterner?|[eE]xternal)?\\s*(?:[wW]eblink|[lL]inks?|[wW]ebseiten?|[wW]ebsites?)\\s*$', 'Weblinks',SOURCE+VISUAL); }; problemsForProjects['*']=function(add){ mw.log.warn('veHint.js: No config for this project!'); add('Placeholder','^.*$',false,SOURCE+VISUAL); }; //'oojs-ui.styles.icons-movement' nicht aufgeführt, da diese Icons auch vom beerbten Suchdialog verwendet werden mw.loader.using([ 'mediawiki.language','mediawiki.util', 'ext.visualEditor.core','ext.visualEditor.desktopArticleTarget','oojs-ui.styles.icons-alerts' ]).then(function(){ initL10N(l10n); init(problemsForProjects[mw.config.get('wgDBname')]||problemsForProjects['*']); mw.hook('userjs.script-ready.veHint').fire(); }); })(jQuery,mediaWiki); //</nowiki>