Year of the Dragon: Through May 28th, claim free Expansion Pack (excluding Vecna Unleashed) or a Greater Elixir of Discovery! Speak to Xatheral in the Hall of Heroes. edit

Thank you for your patience while we continue to upgrade DDOwiki to the latest MediaWiki LTS version. If you find any errors on the site, please visit the Discord chat server and let us know.

Game mechanicsNewbie guideIn developmentDDO StoreSocial Media


ChallengesClassesCollectablesCraftingEnhancementsEpic DestiniesFavorFeats

GlossaryItemsMapsMonstersPlacesQuestsRacesReincarnationSkillsSpells


Please create an account or log in to remove ads, build a reputation, and unlock more editing privileges and then visit DDO wiki's IRC Chat/Discord if you need any help!

MediaWiki:Gadget-vectorMenu.js

From DDO wiki
Jump to navigation Jump to search

Note: After saving, you may have to bypass your browser's cache to see the changes, you can click here or try one of the methods below..

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl+F5 or Ctrl+r ( Command+r on a Mac)
  • Google Chrome: Press Ctrl+ Shift+R ( Command+ Shift+R on a Mac)
  • Internet Explorer: Hold Ctrl while clicking Refresh, or press Ctrl+F5
  • Konqueror: Click Reload or press F5
  • Opera: Clear the cache in Tools ‣ Preferences
/**********************************************************************
 **                ***WARNING: GLOBAL GADGET FILE***                 **
 **         any changes to this file will affect many users          **
 **          please discuss changes on the talk page                 **
 **     (consider dropping the script author a note as well...)      **
 **********************************************************************
 **        SOURCED BY [[MediaWiki:Gadget-vectorMenu.js]]             **
 **********************************************************************/

//<nowiki>
// Version       : 1.0
// Author        : [[U:Technical 13]]
// Script        : [[MW:Gadget-vectorMenu.js]]
// Description   : [[MWt:Gadget-vectorMenu]]
// Documentation : [[MW:Gadget-vectorMenu]]
// GitHub        : 
// Prerequisites : MediaWiki version 1.8 or higher
//                 jStorage via ResourceLoader
//                 Any modern browser or IE8+
// Based on      : https://github.com/MusikAnimal/MoreMenu v4.3.2
//                ( http://enwp.org/User:MusikAnimal/MoreMenu docs )
//
// Text available under the Creative Commons Attribution-ShareAlike License (CC BY-SA 3.0)
//

( function( mw, $ ) {
  var api = new mw.Api(),
    namespaceNumber = mw.config.get( 'wgNamespaceNumber' ),
    canonicalSpecialPageName = mw.config.get( 'wgCanonicalSpecialPageName' ),
    isPageProtected = ( !!mw.config.get( 'wgRestrictionEdit' ) &&
      mw.config.get( 'wgRestrictionEdit' ).length ) ||
      ( !!mw.config.get( 'wgRestrictionCreate' ) &&
      mw.config.get( 'wgRestrictionCreate' ).length ),
    serverName = mw.config.get( 'wgServer' ),
    siteName = mw.config.get( 'wgSiteName' ),
    userGroups = mw.config.get( 'wgUserGroups' ),
    contentLanguage = mw.config.get( 'wgContentLanguage' ),
    articleId = mw.config.get( 'wgArticleId' ),
    mwDBname = mw.config.get( 'wgDBname' ),
    pageName = mw.config.get( 'wgPageName' ),
    actionType = mw.config.get( 'wgAction' ),
    userName = mw.config.get( 'wgRelevantUserName' ) || '',
    isUserSpace,
    metaUserGroups,
    userPermissions,
    currentDate = new Date();
  var escapedPageName = pageName.replace( /[!'"()*]/g, escape ),
    encodedPageName = encodeURIComponent( pageName ),
    escapedUserName = userName.replace( /[?!'()*]/g, escape ),
    encodedUserName = encodeURIComponent( userName );

  $( '#ca-protect,#ca-unprotect,#ca-delete,#ca-undelete' ).remove();// Admin stuff
  $( '#ca-move' ).remove();// Everyone has a move link
  if ( mw.user.options.get( 'gadget-wikEd' ) !== '1' ) {// wikEd bug workaround...
    $( '#ca-purge,#p-cactions' ).remove();//Remove purge and empty menu if not using wiEd.
  }

  var userMenuList = {
    'User' : {
      'User logs' : {
        'All logs' : {
          url : mw.util.getUrl( 'Special:Log', { action: 'view', user: userName } )
        },
        'Block log' : {
          url : mw.util.getUrl( 'Special:Log', { action: 'view', user: userName, type: 'block' } ),
          permissions : [ 'block' ]
        },
        'Deletion log' : {
          url : mw.util.getUrl( 'Special:Log', { action: 'view', user: userName, type: 'delete' } ),
          permissions : [ 'delete' ]
        },
        'Move log' : {
          url : mw.util.getUrl( 'Special:Log', { action: 'view', user: userName, type: 'move' } ),
          permissions : [ 'move' ]
        },
        'Protection log' : {
          url : mw.util.getUrl( 'Special:Log', { action: 'view', user: userName, type: 'protect' } ),
          permissions : [ 'protect' ]
        },
        'Review log' : {
          url : mw.util.getUrl( 'Special:Log', { action: 'view', user: userName, type: 'review' } ),
          permissions : [ 'review' ]
        },
        'Upload log' : {
          url : mw.util.getUrl( 'Special:Log', { action: 'view', user: userName, type: 'upload' } ),
          permissions : [ 'upload' ]
        },
        'User creation log' : {
          url : mw.util.getUrl( 'Special:Log', { action: 'view', user: userName, type: 'newusers' } ),
          groups : [ 'user' ] // any user can create new accounts at [[Special:CreateAccount]]
        },
        'User rights log' : {
          url : mw.util.getUrl( 'Special:Log', { action: 'view', user: userName, type: 'rights' } ),
          addRemoveGroups : true
        }
      },/*
      'RfXs' : {
        'RfAs' : {
          url : mw.util.getUrl( 'Special:PrefixIndex/Wikipedia:Requests_for_adminship/' + userName ),
          style : 'display:none',
          title : 'Requests for Adminship'
        },
        'RfBs' : {
          url : mw.util.getUrl( 'Special:PrefixIndex/Wikipedia:Requests_for_bureaucratship/' + userName ),
          style : 'display:none',
          title : 'Requests for Bureaucratship'
        },
      },*/
      'Blocks' : {
        'Block user' : {
          url : mw.util.getUrl( 'Special:Block/' + userName ),
          userPermissions : 'block',
          blocked : false
        },
        'Change block' : {
          url : mw.util.getUrl( 'Special:Block/' + userName ),
          userPermissions : 'block',
          blocked : true
        },
        'Unblock user' : {
          url : mw.util.getUrl( 'Special:Unblock/' + userName ),
          blocked : true,
          userPermissions : 'block'
        },
        'View block' : {
          url : mw.util.getUrl( 'Special:BlockList', { wpTarget: userName } ),
          blocked : true,
          style : 'color: #EE1111'
        },
        'View block log' : {
          url : mw.util.getUrl( 'Special:Log', { action: 'view', page: userName, type: 'block' } )
        }
      },
      'IP lookup' : {
        'WHOIS' : {
          url : 'http://whois.domaintools.com/' + escapedUserName,
          ipOnly : true
        },
        'rDNS' : {
          url : 'https://www.robtex.com/ip/' + escapedUserName + '.html',
          ipOnly : true
        },
        'Traceroute' : {
          url : 'http://www.domaintools.com/research/traceroute/?query=' + escapedUserName,
          ipOnly : true
        },
        'Geolocate' : {
          url : 'http://whatismyipaddress.com/ip/' + escapedUserName,
          ipOnly : true
        }
      },
      'Change rights' : {
        url : mw.util.getUrl( 'Special:UserRights', { user: 'User:' + userName } ),
        groups : [ 'user' ],
        userAddRemoveGroups : true
      },
      'Checkuser' : {
        url : mw.util.getUrl( 'Special:CheckUser/' + userName ),
        userPermissions : [ 'checkuser' ]
      },
      'Contributions' : {
        url : mw.util.getUrl( 'Special:Contributions/' + userName )
      },
      'Deleted contributions' : {
        url : mw.util.getUrl( 'Special:DeletedContributions/' + userName ),
        userPermissions : [ 'deletedhistory', 'deletedtext' ]
      },
      'Suppressed contribs' : {
        url : mw.util.getUrl( 'Special:Log/suppress', { offender: userName } ),
        userPermissions : [ 'oversight' ]
      },
      'Email user' : {
        url : mw.util.getUrl( 'Special:EmailUser/' + userName ),
        groups : [ 'user' ]
      },
      'Uploads' : {
        url : mw.util.getUrl( 'Special:ListFiles', { user: userName, ilshowall: '1' } ),
        groups : [ 'user' ]
      },
      'User groups' : {
        url : mw.util.getUrl( 'Special:ListUsers', { limit: 1, username: userName } ),
        groups : [ 'user' ]
      },
      'User rights changes' : {
        url : mw.util.getUrl( 'Special:Log', { user: '' , page: 'User:' + userName, type: 'rights' } ),
        groups : [ 'user' ]
      },
    }
  };

  var pageMenuList = {
    'Page' : {
      'Page logs' : {
        'All logs' : {
          url : mw.util.getUrl( 'Special:Log', { action: 'view', page: pageName } )
        },
        'Deletion log' : {
          url : mw.util.getUrl( 'Special:Log', { action: 'view', page: pageName, type: 'delete' } )
        },
        'Move log' : {
          url : mw.util.getUrl( 'Special:Log', { action: 'view', page: pageName, type: 'move' } )
        },
        'Protection log' : {
          url : mw.util.getUrl( 'Special:Log', { action: 'view', page: pageName, type: 'protect' } )
        }
      },/*
      'XfDs' : {
        url : 'javascrit:void(0)'
      },*/
      'Protect page' : {
        url : serverName + '/index.php?title=' + encodedPageName + '&action=protect',
        userPermissions : [ 'protect', 'stablesettings' ]
      },
      'Change protection' : {
        url : mw.util.getUrl( pageName, { action: 'protect' } ),
        userPermissions : [ 'protect', 'stablesettings' ],
        isProtected : true
      },
      'Delete page' : {
        url : serverName + '/index.php?title=' + encodedPageName + '&action=delete' + ( $( '#delete-reason' ).text() ? '&wpReason=' + $( '#delete-reason' ).text() : ''),
        userPermissions : [ 'delete' ],
        pageExists : true
      },
      'Undelete page' : {
        url : mw.util.getUrl( 'Special:Undelete/' + pageName ),
        userPermissions : [ 'undelete' ],
        pageDeleted : true
      },
      'Edit intro' : {
        url : serverName + '/index.php?title=' + encodedPageName + '&action=edit&section=0',
        namespaceRestrict : [ 0, 1, 2, 3, 4, 5, 500, 501 ],
        pageExists : true
      },
      'Latest diff' : {
        url : mw.util.getUrl( pageName, { action: 'view', diff: mw.config.get( 'wgCurRevisionId' ) } ),
        pageExists : true
      },
      'Move page' : {
        url : mw.util.getUrl( 'Special:MovePage/' + pageName ),
        userPermissions : [ 'move' ],
        pageExists : true
      },
      'Purge cache' : {
        url : mw.util.getUrl( pageName, { action: 'purge', forcelinkupdate: true } ),
        pageExists : true
      },
      'Compare page' : {
        url : mw.util.getUrl( 'Special:ComparePages', { page1: pageName, page2: ( pageName.substr( 0, pageName.indexOf( '/' ) ) || pageName ) } ),
        pageExists : true
      }/*,
      'Subpages' : {
        url : mw.util.getUrl( 'Special:PrefixIndex/' + pageName + '/' ),
      },*/// Not yet available, but I want it to be.
    }
  };

  var dependencies = [ ];

  if ( !$.jStorage ) dependencies.push( 'jquery.jStorage' );
  if ( !Object.keys ) dependencies.push( 'es5-shim' );

  // initialize script
  mw.loader.using( dependencies, function() {
    var menus = [ ];

    if ( namespaceNumber === 2 || namespaceNumber === 3 || canonicalSpecialPageName === 'Contributions' || !!mw.util.getParamValue( 'user' ) ) {
      isUserSpace = true;
      menus.push( userMenuList );
    }
    if ( namespaceNumber >= 0 ) menus.push( pageMenuList );

    init( menus, function(data) {
      completePageLinks();
      if ( isUserSpace ) completeUserLinks( data[ 0 ].query );
    } );
  } );

  // custom callback functions for these menus

  function completePageLinks() {
    $( '#c2-page-xfds' ).hide();

    $( '#p-views ul' ).on( 'beforeTabCollapse', function() {
      if ( $( '#ca-history' ).hasClass( 'collapsible' ) ) {
        $( '#p-page2' ).find( 'ul' ).append( $( '#ca-history' ).detach() );
      }
    } );
  }

  function completeUserLinks( query ) {
    apiGet( {
      list : 'logevents',
      letype : 'block',
      letitle : 'User:' + userName,
      lelimit : 1
    } ).done( function( data ) {
      if ( data.query.logevents.length === 0) {
        $( '#c2-user-blocks-view_block_log' ).remove();
      }
      if ( $( '#c2-user-blocks' ).find( 'li' ).length === 0 ) {
        $( '#c2-user-blocks' ).remove();
      }
    } );

    /*var rfxs = {
      'DDO:Requests for adminship' : 'rfas',
      'DDO:Requests for bureaucratship' : 'rfbs',
    };

    $( '#c2-user-rfxs' ).hide();*/
  }

  function addListeners() {
    $( '.c2-hover-menu' ).each( function() {
      $( this ).hover( function() {
        $el = $( this ).find( '.submenu' );
        $el.css( {
          left : $( this ).outerWidth(),
          top : '-1px',
          'border-top-width' : 1
        } );
        $el.show();
      }, function() {
        $( this ).find( '.submenu' ).hide();
      } );
    } );
  }

  function apiGet( params ) {
    return api.get(
      $.extend( params, {
        action: 'query'
      } )
    );
  }

  function canAddRemoveGroups( groups, permissions ) {
    if ( permissions && permissions.indexOf( 'userrights' ) >= 0 ) return true;
    var ret = false;
    for ( var i = 0; i < groups.length; i++ ) {
      if ( metaUserGroups[ groups[ i ] ] && metaUserGroups[ groups[ i ] ].addRemoveGroups ) {
        ret = true;
        break;
      } else {
        // clear cache and fallback to false
        $.jStorage.deleteKey( 'metaUserGroups' );
        ret = false;
      }
    }
    return ret;
  }

  // scope is an array, returns true if all elements in 'array' exist in scope
  function containsArray( array, index, last ) {
    if ( !index ) {
      index = 0;
      last = 0;
      this.sort();
      array.sort();
    }
    return index === array.length
      || ( last = this.indexOf( array[ index ], last ) ) > -1
      && containsArray.call( this, array, ++index, ++last );
  }

  function generateMenuContent( tabName, menuList, userData, userPermissions ) {
    var html = '';
    $.each( menuList, function( name, action ) {
      if ( action ) {
        var newHtml = '';
        if ( !action.url ) {
          newHtml += '<li style="position: relative;" id="' + linkId( tabName, name ) + '" class="c2-hover-menu">' +
                '<a style="font-weight: bold">' + name + '&hellip;</a>' +
                  '<div class="submenu menu" style="display: none; position: absolute;"><ul>';

          $.each( action, function( k, v ) {
            newHtml += linkHtml( tabName, k, v, name, userData, userPermissions );
          } );
          newHtml += '</ul></div></li>';
          if ( $( newHtml ).last().find( '.submenu li' ).length === 0 ) {
            newHtml = '';
          }
        } else {
          newHtml += linkHtml( tabName, name, action, null, userData, userPermissions );
        }
        html += newHtml;
      }
    } );
    return html;
  }

  function hasConditional( permitted, given ) {
    permitted = $.makeArray( permitted );
    given = $.makeArray( given );
    if ( !permitted.length ) {
      return true;
    } else if ( !given.length ) {
      return false;
    } else {
      var valid = false;
      for ( var i = 0; i < given.length; i++ ) {
        if ( $.inArray( given[ i ], permitted ) >= 0 ) {
          valid = true;
          break;
        }
      }
      return valid;
    }
  }

  function linkId( tabName, name, parent ) {
    return 'c2-' + sanitize( tabName.toLowerCase() ) + '-' + ( parent ? sanitize( parent ) + '-' : '') + sanitize( name );
  }

  function linkHtml( tabName, name, action, parent, userData, userPermissions ) {
    var validations =
      /* namespace          */ ( hasConditional( action.namespaceRestrict, namespaceNumber ) || !hasConditional( action.namespaceExclude, namespaceNumber ) ) &&
      /* existence          */ ( ( action.pageExists && articleId > 0 ) || ( !action.pageExists ) ) &&
      /* deleted            */ ( action.pageDeleted ? articleId === 0 && mw.config.get( 'wgIsArticle' ) === false : true ) &&
      /* protected          */ ( action.isProtected ? isPageProtected : true ) &&
      /* database           */ hasConditional( action.databaseRestrict, mwDBname ) &&
      /* notice project     *//* hasConditional( action.noticeProjectRestrict, noticeProject ) &&*/
      /* user's user groups */ hasConditional( action.userGroups, userGroups ) &&
      /* user's permissions */ hasConditional( action.userPermissions, userPermissions ) &&
      /* can change groups  */ ( action.userAddRemoveGroups ? canAddRemoveGroups( userGroups, userPermissions ) : true );

    if ( isUserSpace ) {
      // FIXME: find something better than userData.invalid === '' for checking if IP
      validations &=
        /* their user groups  */ hasConditional( action.groups, userData.groups ) &&
        /* their permissions  */ hasConditional( action.permissions, userData.rights ) &&
        /* they're blocked    */ ( action.blocked !== undefined ? !!userData.blockid === action.blocked : true ) &&
        /* can change groups  */ ( action.addRemoveGroups ? canAddRemoveGroups( userData.groups, userData.rights ) : true ) &&
        /* IP                 */ ( action.ipOnly ? userData.invalid === '' : true );
    }

    if ( !!validations ) {
      return '<li id=' + linkId( tabName, name, parent ) + '><a href="' + action.url + '" title="' + ( action.title || '' ) + '" ' + ( action.style ? 'style="' + action.style + '"' : '' ) + '>' + name + '</a></li>';
    } else {
      return '';
    }
  }

  function sanitize( name ) {
    return name.toLowerCase().replace( / /g, '_' );
  }

  function init( menus, fn ) {
    var promises = new Array( 3 ),
        cacheDate = $.jStorage.get( 'mmCacheDate' ),
        expired = cacheDate < currentDate;

    if ( isUserSpace ) {
      promises[ 0 ] = apiGet( {
        list : 'users|blocks',
        ususers : userName,
        bkusers : userName,
        usprop : 'blockinfo|groups|rights',
        bkprop : 'id'
      } );
    }

    if ( expired || !( userPermissions = $.jStorage.get( 'mmUserRights' ) ) ) {
      promises[ 1 ] = mw.user.getRights();
    }

    if ( expired || !( metaUserGroups = $.jStorage.get( 'mmMetaUserGroups' ) ) ) {
      promises[ 2 ] = apiGet( {
        meta : 'siteinfo',
        siprop : 'usergroups'
      } );
    }

    $.when.apply( this, promises ).done( function ( data, userRightsData, metaData ) {
      var userData;

      if ( data ) {
        userData = data[ 0 ].query.users[ 0 ];

        if ( !userData ) {
          // FIXME: add functionality to only show menu based on custom function;
          //    temporary fix so that script doesn't break on pages of users that don't exist
          isUserSpace = false;
          for ( var j = 0; j < menus.length; j++ ) {
            if ( !!menus[ j ].User ) menus.splice( j, 1 );
          }
        } else if ( userData.invalid === '' ) {
          userData.groups = [ ];
          userData.rights = [ ];
          if ( data[ 0 ].query.blocks.length ) {
            userData.blockid = data[ 0 ].query.blocks[ 0 ].id;
          }
        }
      }

      if ( userRightsData ) {
        userPermissions = $.jStorage.set( 'mmUserRights', userRightsData );
      }

      if ( metaData ) {
        metaUserGroups = {};
        $.each( metaData[ 0 ].query.usergroups, function ( i, el ) {
          metaUserGroups[ el.name ] = {
            permissions : el.rights,
            addRemoveGroups : !!el.add || !!el.remove
          };
        } );
        $.jStorage.set( 'mmMetaUserGroups', metaUserGroups );
      }

      if ( expired ) {
        var newDate = new Date();
        $.jStorage.set( 'mmCacheDate', newDate.setDate( newDate.getDate() + 7 ) );
      }

      for ( var i = 0; i < menus.length; i++ ) {
        var tabName = Object.keys( menus[ i ] )[ 0 ];
        var html =  '<div id="p-' + tabName.toLowerCase() + '2" class="vectorMenu" style="z-index: 99;">' +
          '<h3><span>' + tabName + '</span><a href="#" title="' + tabName + '"></a></h3>' +
          '<div class="menu"><ul>';
        html += generateMenuContent( tabName, menus[ i ][ tabName ], userData, userPermissions );
        html += '</ul></div></div>';
        if ( $( '#p-cactions' )[ 0 ] ) {
          $( html ).insertAfter( $( '#p-cactions' ) );
        } else {
          $( html ).insertAfter( $( '#p-views' ) );
        }
        addListeners();
      }

      if ( typeof fn === 'function' ) fn( data, userPermissions );
    } );
  }
} )( mediaWiki, jQuery );
//</nowiki> [[C:Gadgets]]