User:Mith/common.js

From Wikidata
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
mw.loader.load( '//www.wikidata.org/w/index.php?title=User:Joern/altLabels.js&action=raw&ctype=text/javascript' ); // [[User:Joern/altLabels.js]]

//importScript("User:Magnus Manske/wikidata useful.js");// [[User:Magnus Manske/wikidata useful.js]];//

//importScript( 'User:Mith/quickpresets_settings.js' );// [[User:Mith/quickpresets.js]];//
importScript( 'User:MichaelSchoenitzer/quickpresets.js' );// [[User:MichaelSchoenitzer/quickpresets.js]];

importScript ( 'User:Magnus Manske/duplicate item.js' );

// importScript ( 'User:TomT0m/classification.js' ); //

if ( mw.config.get("wgDBname") !== 'ruwiki')
    mediaWiki.loader.load( '//ru.wikipedia.org/w/index.php?title=MediaWiki:WEF_AllEditors.js&action=raw&ctype=text/javascript' );

importScript( 'User:Tpt/viaf.js' );

importScript ( 'User:Frettie/consistency check add.js' );
mw.loader.load( '//www.wikidata.org/w/index.php?title=User:Bargioni/UseAsRef.js&action=raw&ctype=text/javascript' ); // [[User:Bargioni/UseAsRef.js]]
mw.loader.load( '//www.wikidata.org/w/index.php?title=User:Ricordisamoa/GeneaWiki.js&action=raw&ctype=text/javascript' ); // [[User:Ricordisamoa/GeneaWiki.js]]


/*
This script enables users to easily change order of values in any statement.
It puts a blue button to all statements with multiple values.
Upon clicking it, two (up and down) arrows appear near each value, 
which can be used to move values up or down relative to neighboring values.
When the desired order is reached, press "save" button to make an edit, which saves the new order.

Also, upon clicking a blue button, a drag'n'drop is enabled, so that user can move values to 
the desired positions by dragging them.
To do this, point your mouse over the value you want to move, press and hold the left mouse button, 
move the value to the desired place and release the mouse button.
When the desired order is reached, press "save" button to make an edit, which saves the new order.

To enable this script for your account, navigate to https://www.wikidata.org/wiki/Special:MyPage/common.js 
and add the following code to the page (or create a page with this code):
mw.loader.load( '//www.wikidata.org/w/index.php?title=User:Tohaomg/rearrange_values.js&action=raw&ctype=text/javascript' );
*/

(function($, mw)
{
  //this should work only in main namespace or in "property" namespace
  if( mw.config.get('wgNamespaceNumber')!==0 && mw.config.get('wgNamespaceNumber')!==120 ) {return;}
  
  //url beginning for image files from commons
  var commons_upload = 'https://upload.wikimedia.org/wikipedia/commons/';
  //original orders of values to which to return, if "cancel" is pressed
  var statement_original_orders = {};
  
  //texts for buttons in different languages
  var messages = mw.message().map.values;
  
  //rearrange-button
  function ra_img(element_id)
  {
    return $('<img/>').attr('src', commons_upload + 'b/b0/Symbol_merge_vote.svg')
    	.css('width', '20px').css('margin-top', '10px').css('cursor', 'pointer')
    	.click(function(e) {statement_selected(element_id);});
  }

  //add rearrange-buttons to all statements with multiple values
  $( ".wikibase-statementgrouplistview" ).children().children().each(
  function(index)
  {
    var values_elements = $(this).find(":nth-child(2)").find(".wikibase-statementview");
    if(values_elements.length >= 2)
    {
      var element_id = $(this).attr('id');
      var img_div = $('<div></div>').attr('id', 'button' + element_id).append(ra_img(element_id));
      $(this).children().first().children().first().append('<br/>').append(img_div);
    }
  });
  
  //if one of rearrange-buttons is pressed, add arrows-buttons to each value and add "save" and "cancel"
  function statement_selected(statement_p)
  {
    //"save" and "cancel" buttons
    var save_text = messages['wikibase-save']; if(typeof save_text === 'undefined') {save_text = 'save';}
    var cancel_text = messages['wikibase-cancel']; if(typeof cancel_text === 'undefined') {cancel_text = 'cancel';}

    var button_save_icon   = $('<span></span>')
    	.addClass('ui-button-icon-primary').addClass('ui-icon').addClass('ui-icon-circle-check');
    var button_cancel_icon = $('<span></span>')
    	.addClass('ui-button-icon-primary').addClass('ui-icon').addClass('ui-icon-circle-close');

    var button_save   = $('<button></button>')
    	.css('background', 'transparent')
    	.addClass('ui-button').addClass('ui-widget').addClass('ui-state-default')
    	.addClass('ui-corner-all').addClass('ui-button-text-icon-primary').addClass('ui-button-green')
    	.click(function(e) {save(statement_p);})
    	.attr('aria-disabled', 'false').attr('role', 'button').attr('type', 'button')
    	.append(button_save_icon)
    	.append( $('<span></span>').addClass('ui-button-text').text(save_text) );
    var button_cancel = $('<button></button>')
    	.css('background', 'transparent')
    	.addClass('ui-button').addClass('ui-widget').addClass('ui-state-default')
    	.addClass('ui-corner-all').addClass('ui-button-text-icon-primary').addClass('ui-button-red')
    	.click(function(e) {cancel(statement_p);})
    	.attr('aria-disabled', 'false').attr('role', 'button').attr('type', 'button')
    	.append(button_cancel_icon)
    	.append( $('<span></span>').addClass('ui-button-text').text(cancel_text) );

    $('#button' + statement_p).empty().append(button_save).append(button_cancel);
    
    //list to store original order of values to return to if "cancel" is pressed
    var original_order = [];

    //some variable needed for drag and drop
    var element_height;
    var dragged_node_id; var node_new_position;
    var prev_node; var next_node;
    var first_node; var last_node;
    var dragover_counter = 0; var index_of_dragged_node;

    //iterate over each value
    $('#' + statement_p).find(":nth-child(2)").find(".wikibase-statementview").each(
    function(index)
    {
      //dollar sign should be removed from 'id's because it is a special character in jquery
      var value_id = ($(this).attr('id')).replace('$', '');
      $(this).attr('id', value_id);

      //add current id to the list for original values
      original_order.push(value_id);

      //add buttons to current value
      var arrow_up   = $('<img/>').attr('src', commons_upload + '2/28/Symbol_arrow_up.svg')
    	.css('width', '20px').css('margin-left', '10px').css('cursor', 'pointer').click(function(e) {move_value_up(value_id);});
      var arrow_down = $('<img/>').attr('src', commons_upload + 'f/f7/Symbol_arrow_down.svg')
    	.css('width', '20px').css('margin-left', '10px').css('cursor', 'pointer').click(function(e) {move_value_down(value_id);});
      var div_arrows = $('<div></div>').append(arrow_up).append(arrow_down)
        .css('float', 'right').css('margin-right', '10px').addClass('move_arrows_block');
      $(this).find('.wikibase-edittoolbar-container').append(div_arrows);

      //make the values draggable
      $(this).attr('draggable', 'true');
      $(this).on('dragstart', function(event)
      {
        dragged_node_id = event.target.id;
        if(!dragged_node_id) return;
        element_height = document.getElementById(dragged_node_id).offsetHeight;
        setTimeout( function() { $('#' + dragged_node_id).css('display', 'none'); }, 0);
      });
    });
    
    //add original order of this statement to the list of original orders of all statements
    statement_original_orders[statement_p] = original_order;
    
    //what to do when an element is being dragged
    $('body').on('dragover', function(event)
    {
      event.preventDefault();
      
      //get positions of all nodes
      var nodes_positions = [];
      $('#' + statement_p).find(":nth-child(2)").find(".wikibase-statementview").each(
        function(index)
        {
          if( $(this).attr('id')==dragged_node_id ) {index_of_dragged_node = index; return;}
          var element_id = $(this).attr('id');
          var element = document.getElementById(element_id);
          if(!element) return;
          var node_position = element.getBoundingClientRect();
          nodes_positions.push( {id: element_id, y: (node_position.top + node_position.bottom)/2} );
          if(dragover_counter==0 && index>index_of_dragged_node) { nodes_positions[nodes_positions.length-1].y += element_height; }
          $(this).css('marginTop', ''); $(this).css('marginBottom', '');
        });
      
      //get position of the node currently being dragged
      node_new_position = 0;
      first_node = nodes_positions[0].id;
      last_node = nodes_positions[nodes_positions.length-1].id;
      for(var i=0; i<nodes_positions.length; i++)
      {
        if(nodes_positions[i].y < event.clientY)
        {
          node_new_position = i+1
          prev_node = nodes_positions[i].id;
          next_node = (i+1<nodes_positions.length) ? nodes_positions[i+1].id : '';
        }
        else {break;}
      }
      
      //give space for the node currently being dragged
      if(node_new_position == 0)
      { $('#' + first_node).css('marginTop', element_height + 'px'); }
      else if(node_new_position == nodes_positions.length)
      { $('#' + last_node).css('marginBottom', element_height + 'px'); }
      else
      {
        $('#' + prev_node).css('marginBottom', element_height/2 + 'px');
        $('#' + next_node).css('marginTop', element_height/2 + 'px');
      }
      dragover_counter++;
    });
    
    //what to do when element is dropped
    $('body').on('drop', function(event)
    {
      event.preventDefault();
      
      if(node_new_position == 0) { $('#' + first_node).before( $('#' + dragged_node_id) ); }
      else { $('#' + prev_node).after( $('#' + dragged_node_id) ); }
    });
    
    //what to do when drag ends (whether by drop or by failing the drag)
    $('body').on('dragend', function(event)
    {
      $('#' + statement_p).find(":nth-child(2)").find(".wikibase-statementview").each(
        function(index) { $(this).css('marginTop', ''); $(this).css('marginBottom', '');
      });
        
      $('#' + dragged_node_id).css('display', '');
      dragover_counter = 0;
    });
  }
  
  
  //move value one position up
  function move_value_up(value_id)
  {
    var previous_id = $('#' + value_id).prev().attr('id');
    if(!previous_id) {return;}
    $('#' + previous_id).before($('#' + value_id));
  }
  
  //move value one position down
  function move_value_down(value_id)
  {
    var previous_id = $('#' + value_id).next().attr('id');
    if(!previous_id) {return;}
    $('#' + previous_id).after($('#' + value_id));
  }
  
  //function to replace "save" and "cancel" buttons with rearrange-button and to remove arrow buttons
  function statement_exited(statement_p)
  {
    //replace "save" and "cancel" buttons with rearrange-button
    var img = $('<img/>').attr('src', commons_upload + 'b/b0/Symbol_merge_vote.svg')
    	.css('width', '20px').css('margin-top', '10px').click(function(e) {statement_selected(statement_p)});
    $('#button' + statement_p).empty().append(ra_img(statement_p));
    //remove arrow buttons
    $('#' + statement_p).find('.move_arrows_block').remove();
    //make values not draggable
    $('#' + statement_p).find(":nth-child(2)").find(".wikibase-statementview").each( function(index) { $(this).attr('draggable', 'false'); });
  }
  
  //if button "cancel" is pressed
  function cancel(statement_p)
  {
    //if any value was deleted, it should be removed from the original order
    for(var i=0; i<statement_original_orders[statement_p].length; i++)
    {
      if($('#' +statement_original_orders[statement_p][i]).length === 0)
      {statement_original_orders[statement_p].splice(i, 1);}
    }
    //put values in the order they were before clicking rearrange-buttons
    for(var j=0; j<statement_original_orders[statement_p].length-1; j++)
    {
      $('#' +  $('#' + statement_p).children().eq(1).find(".wikibase-statementview").eq(j).attr('id')  )
        .before($('#' + statement_original_orders[statement_p][j] ));
    }
    //replace "save" and "cancel" buttons with rearrange-button, remove arrow buttons
    statement_exited(statement_p);
  }
  
  //if button "save" is pressed
  function save(statement_p)
  {
    //get JSON for values (claims)
    var claims;
    $.ajax(
    {
	 url: mw.util.wikiScript('api'),
	 type: 'POST',
	 dataType: 'json',
	 data:
	 {
	  action: 'wbgetentities',
	  ids: mw.config.get('wgTitle'),
	  format: 'json'
	 }
    }).done(function(data)
    {
      //when response is received, proceed
      claims = data.entities[mw.config.get('wgTitle')].claims[statement_p];
      var i;
      
      //check if the order changed at all
      //for this, firstly, get a list of values as they are now
      var actual_claims = [];
      var id;
      $('#' + statement_p).find(":nth-child(2)").find(".wikibase-statementview").each(
      	function(index)
      	{
      	  id = $(this).attr('id');
      	  //if it is a value, which was just added
      	  if(id=='new')
      	  {
      	    id = $(this).attr('class');
      	    try {
      	    	id = id.match(/wikibase-statement-([QPq].+)$/)[1].replace('$', '');
      	    } catch (e) {
      	    	// no match.
      	    	return;
      	    }
      	  }
      	  actual_claims.push(id);
      	});
      //then compare this list with the list of values in original order
      var same = true;
      for(i=0; i<claims.length; i++)
      {if(claims[i].id.replace('$', '')!=actual_claims[i]) {same = false; break;}}
      //if order did not change, no need to make an edit
      if(same) {statement_exited(statement_p); return;}
      
      //remove values in old order
      var remove_claims = [];
      for(i=0; i<claims.length; i++) {remove_claims.push('{"id":"' + claims[i].id + '","remove":""}');}
      remove_claims = remove_claims.join(',');
      
      //put values in new order
      var indexed_claims = {};
      for(i=0; i<claims.length; i++)
      {indexed_claims[(claims[i].id).replace('$', '')] = claims[i];}
      var add_claims = [];
      for(i=0; i<actual_claims.length; i++)
      {add_claims.push(JSON.stringify(indexed_claims[actual_claims[i]]))}
      add_claims = add_claims.join(',');
    
      //commit the edit
      var response = $.ajax(
      {
	   url: mw.util.wikiScript('api'),
	   type: 'POST',
	   dataType: 'json',
	   data:
	   {
	    action: 'wbeditentity',
	    id: mw.config.get('wgTitle'),
	    summary: 'Changing order of values for statement ' + statement_p + 
	      ' using [[User:Tohaomg/rearrange values.js|rearrange values.js]]',
	    token: mw.user.tokens.get('csrfToken'),
	    data: '{"claims":[' + remove_claims + ',' + add_claims + ']}'
	   }
      });
    
      //replace "save" and "cancel" buttons with rearrange-button, remove arrow buttons
      statement_exited(statement_p);
    });
  }
}
(jQuery, mediaWiki));