|
|
Řádek 1: |
Řádek 1: |
| mw.hook( 've.activationComplete' ).add(function(){ | | mw.hook( 've.activationComplete' ).add(function(){ |
− | /* Translate the following to your language: */
| |
− | if (!mw.messages.exists( 've-SearchAndReplaceDialog-title' )) {
| |
− | mw.messages.set({
| |
− | 've-SearchAndReplaceDialog-title': 'Search and replace',
| |
− | 've-SearchAndReplaceDialog-from-label': 'From:',
| |
− | 've-SearchAndReplaceDialog-to-label': 'To:',
| |
− | 've-SearchAndReplaceDialog-from-placeholder': 'From text',
| |
− | 've-SearchAndReplaceDialog-to-placeholder': 'To text',
| |
− | 've-SearchAndReplaceDialog-replaceAll': 'Repalce all',
| |
− | 've-SearchAndReplaceDialog-replace': 'Repalce',
| |
− | 've-SearchAndReplaceDialog-matchcase': 'Match case',
| |
− | 've-SearchAndReplaceDialog-replace-complete': 'Found and replaced $1 occurrences',
| |
− | 've-ReplaceTool-ToolbarButton': 'Replace'
| |
− | });
| |
− | }
| |
− | /* end of translations */
| |
− |
| |
− | /*!
| |
− | * VisualEditor replace gadget
| |
− | *
| |
− | * @copyright [[User:ערן|Eranroz]] and [[User:Ravid ziv|Ravid ziv]]
| |
− | * @license The MIT License (MIT)
| |
− | */
| |
− | function extractText(){
| |
− | var nodes = [];
| |
− | var model = ve.instances[0].model;
| |
− | function getTextNodes( obj ) {
| |
− | var i;
| |
− |
| |
− | for ( i = 0; i < obj.children.length; i++ ) {
| |
− | if ( obj.children[i].type == 'text'){
| |
− | nodes.push(obj.children[i]);
| |
− | }
| |
− |
| |
− | if ( obj.children[i].children ) {
| |
− | getTextNodes( obj.children[i] );
| |
− | }
| |
− | }
| |
− | }
| |
− | getTextNodes(ve.instances[0].model.documentModel.getDocumentNode());
| |
− | return nodes;
| |
− | }
| |
− |
| |
− | function searchAndReplace( fromText, toText, replaceAll, matchCase ) {
| |
− | var textNodes = extractText();
| |
− | var model = ve.instances[0].model;
| |
− | var firstIndex = 0;
| |
− | var numReplacements = 0;
| |
− | for (var nodeI = 0; nodeI < textNodes.length; nodeI++) {
| |
− | var node = textNodes[nodeI];
| |
− | var nodeRange = node.getRange();
| |
− | var nodeData = model.getFragment( nodeRange ).getData();
| |
− | var nodeText = $.map(nodeData, function( e ){
| |
− | if ( e instanceof Array){ return e[0]; } else { return e; }
| |
− | }).join('');
| |
− |
| |
− |
| |
− | var fromIndex = matchCase? nodeText.toUpperCase().indexOf( fromText.toUpperCase(), firstIndex ) : nodeText.indexOf( fromText, firstIndex );
| |
− | if ( fromIndex == -1 ) {
| |
− | firstIndex = 0;
| |
− | continue;
| |
− | }
| |
− | var start = nodeRange.from+fromIndex;
| |
− | var end = start+fromText.length;
| |
− | if (!replaceAll && model.selection.start > start) {
| |
− | continue;//skip replacements before selection
| |
− | }
| |
− | var removeRange = new ve.Range( start, end );
| |
− | var transaction = ve.dm.Transaction.newFromReplacement(
| |
− | ve.instances[0].view.documentView.model,
| |
− | removeRange,
| |
− | toText
| |
− | );
| |
− | var newSelection = new ve.Range(0,0);
| |
− | if (!replaceAll) {
| |
− | newSelection = new ve.Range( start, start+toText.length );
| |
− | }
| |
− | ve.instances[0].view.changeModel(transaction, newSelection);
| |
− | numReplacements++;
| |
− | if (!replaceAll) {
| |
− | break;
| |
− | }
| |
− | firstIndex = fromIndex + toText.length;
| |
− | nodeI = nodeI -1;
| |
− | }
| |
− | if (numReplacements==0 || replaceAll) {
| |
− | mw.notify( mw.msg( 've-SearchAndReplaceDialog-replace-complete', numReplacements ) );
| |
− | }
| |
− | }
| |
− |
| |
− | ve.ui.SearchAndReplaceDialog = function( manager, config ) {
| |
− | // Parent constructor
| |
− | ve.ui.SearchAndReplaceDialog.super.call( this, manager, config );
| |
− |
| |
− | };
| |
− | /* Inheritance */
| |
− |
| |
− | OO.inheritClass( ve.ui.SearchAndReplaceDialog, ve.ui.FragmentDialog );
| |
− |
| |
− | ve.ui.SearchAndReplaceDialog.prototype.getActionProcess = function ( action ) {
| |
− | var fromVal = this.fromInput.getValue(),
| |
− | toVal = this.toInput.getValue(),
| |
− | matchCase = this.matchCaseCheckbox.getValue();
| |
− |
| |
− | if ( action === 'replace' ) {
| |
− | return new OO.ui.Process( function () {
| |
− | searchAndReplace( fromVal, toVal, false, matchCase );
| |
− | }, this );
| |
− | } else if ( action === 'replace-all' ) {
| |
− | return new OO.ui.Process( function () {
| |
− | searchAndReplace( fromVal, toVal, true, matchCase );
| |
− | this.close( );
| |
− | }, this );
| |
− | }
| |
− | return ve.ui.MWMediaDialog.super.prototype.getActionProcess.call( this, action );
| |
− | }
| |
− |
| |
− | ve.ui.SearchAndReplaceDialog.prototype.getBodyHeight = function () {
| |
− | return 200;
| |
− | };
| |
− |
| |
− | /* Static Properties */
| |
− | ve.ui.SearchAndReplaceDialog.static.name = 'search';
| |
− | ve.ui.SearchAndReplaceDialog.static.title = mw.msg( 've-SearchAndReplaceDialog-title' );
| |
− | ve.ui.SearchAndReplaceDialog.static.size = 'medium';
| |
− |
| |
− | ve.ui.SearchAndReplaceDialog.static.actions = [
| |
− | {
| |
− | 'action': 'replace',
| |
− | 'label': mw.msg( 've-SearchAndReplaceDialog-replace' ),
| |
− | 'flags': [ 'constructive' ],
| |
− | 'modes': 'insert'
| |
− | },
| |
− | {
| |
− | 'label': OO.ui.deferMsg( 'visualeditor-dialog-action-cancel' ),
| |
− | 'flags': 'safe',
| |
− | 'modes': [ 'edit', 'insert', 'select' ]
| |
− | },
| |
− | {
| |
− | 'action': 'replace-all',
| |
− | 'label': mw.msg( 've-SearchAndReplaceDialog-replaceAll' ),
| |
− | 'flags': [ 'constructive' ],
| |
− | 'modes': 'insert'
| |
− | }
| |
− | ];
| |
− |
| |
− | ve.ui.SearchAndReplaceDialog.prototype.initialize = function () {
| |
− | ve.ui.SearchAndReplaceDialog.super.prototype.initialize.call( this );
| |
− | this.panel = new OO.ui.PanelLayout( { '$': this.$, 'scrollable': true, 'padded': true } );
| |
− | this.inputsFieldset = new OO.ui.FieldsetLayout( {
| |
− | '$': this.$
| |
− | } );
| |
− | // input from
| |
− | this.fromInput = new OO.ui.TextInputWidget(
| |
− | { '$': this.$, 'multiline': false, 'placeholder': mw.msg( 've-SearchAndReplaceDialog-from-placeholder' ) }
| |
− | );
| |
− | //input to
| |
− | this.toInput = new OO.ui.TextInputWidget(
| |
− | { '$': this.$, 'multiline': false, 'placeholder': mw.msg( 've-SearchAndReplaceDialog-to-placeholder' ) }
| |
− | );
| |
− | this.fromField = new OO.ui.FieldLayout( this.fromInput, {
| |
− | '$': this.$,
| |
− | 'label': mw.msg( 've-SearchAndReplaceDialog-from-label' )
| |
− | } );
| |
− | this.toField = new OO.ui.FieldLayout( this.toInput, {
| |
− | '$': this.$,
| |
− | 'label': mw.msg( 've-SearchAndReplaceDialog-to-label' )
| |
− | } );
| |
− |
| |
− |
| |
− | this.matchCaseCheckbox = new OO.ui.CheckboxInputWidget( {
| |
− | '$': this.$
| |
− | } );
| |
− | var matchCaseField = new OO.ui.FieldLayout( this.matchCaseCheckbox, {
| |
− | '$': this.$,
| |
− | 'align': 'inline',
| |
− | 'label': mw.msg( 've-SearchAndReplaceDialog-matchcase' )
| |
− | } );
| |
− |
| |
− | this.inputsFieldset.$element.append(
| |
− | this.fromField.$element,
| |
− | this.toField.$element,
| |
− | matchCaseField.$element
| |
− | );
| |
− | this.panel.$element.append( this.inputsFieldset.$element );
| |
− | this.$body.append( this.panel.$element );
| |
− |
| |
− | }
| |
− |
| |
− | ve.ui.windowFactory.register( ve.ui.SearchAndReplaceDialog );
| |
− |
| |
− | //---------- replace tool ------------------
| |
− |
| |
− | function ReplaceTool( toolGroup, config ) {
| |
− | OO.ui.Tool.call( this, toolGroup, config );
| |
− |
| |
− | }
| |
− | OO.inheritClass( ReplaceTool, OO.ui.Tool );
| |
− |
| |
− | ReplaceTool.static.name = 'ReplaceTool';
| |
− | ReplaceTool.static.title = mw.msg('ve-ReplaceTool-ToolbarButton');
| |
− |
| |
− | ReplaceTool.prototype.onSelect = function () {
| |
− | this.toolbar.getSurface().execute( 'window', 'open', 'search', null );
| |
− | };
| |
− |
| |
− | ReplaceTool.prototype.onUpdateState = function () {
| |
− | this.setActive( false );
| |
− | };
| |
− |
| |
− | ve.ui.toolFactory.register( ReplaceTool );
| |
− |
| |
| | | |
| }); | | }); |