User:Equazcion/Floater.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
mw.loader.using( ['mediawiki.util', 'mediawiki.user'], function () {
	
	return;
	// Disable for now, as this script is throwing exceptions


  var imageHistory = "https://upload.wikimedia.org/wikipedia/commons/1/1d/Clock_simple_white.svg";
  var imageEdit = "http://upload.wikimedia.org/wikipedia/commons/e/ec/Btn_edit.gif";
  var imageSwitch = "https://upload.wikimedia.org/wikipedia/commons/e/e8/Play_blauw.png";
  
  // Load prerequisites
  importStylesheet('User:Equazcion/Floater.css');
  loadJQViewport();
  
  // Predict a static floater height
  var floaterHeight = 31;
  
  // Create/insert empty Floater div
  $('#mw-head').prepend('<div hidden="hidden" class="floater" ' + 
    'style="top:' + '-' + floaterHeight + 'px;' +
    '">.</div>');
  
  // Grab the div
  var floater = $('.floater');
  
  // Set URL prefix
  var pre = location.protocol + '//' + mw.config.get('wgPageContentLanguage') + '.' + mw.config.get('wgNoticeProject') + '.org' + '/w/index.php?title=';
  
  // Construct the page title line here. Long titles will need to be truncated.
  if (mw.config.get('wgPageName').length > 40){
    if (mw.config.get('wgNamespaceNumber') == 0){
      pageNS = '';
    } else if (mw.config.get('wgNamespaceNumber') == 4) {
      pageNS = 'WP:';
    } else if (mw.config.get('wgNamespaceNumber') == 5) {
      pageNS = 'WP Talk:';
    } else if (mw.config.get('wgNamespaceNumber') == 8) {
      pageNS = 'MW:';
    } else if (mw.config.get('wgNamespaceNumber') == 9) {
      pageNS = 'MW Talk:';
    } else if (mw.config.get('wgNamespaceNumber') == 14) {
      pageNS = 'Cat:';
    } else if (mw.config.get('wgNamespaceNumber') == 15) {
      pageNS = 'Cat talk:';
    } else {
      pageNS = mw.config.get('wgCanonicalNamespace') + ':';
    }
    var pageTitle = pageNS + mw.config.get('wgTitle').substr(0,7) + '...' + mw.config.get('wgTitle').substr(-15);
    var titleLine = '<li style="margin-right:10px;font-size:0.85em;"><abbr style="border-bottom:none;" title="' + mw.config.get('wgPageName').replace(/_/g,' ') + '">' + pageTitle.replace(/_/g,' ') + '</abbr></li>';
  } else {
    var titleLine = '<li style="margin-right:10px;font-size:0.9em;">' + mw.config.get('wgPageName').replace(/_/g,' ') + '</li>';
  }
  
  // If the current page has an "add section" tab, construct a link 
  if ($('#ca-addsection').length > 0){
    var addSection = '<li><a href="' + pre + mw.config.get('wgPageName') + '&action=edit&section=new' + '"><span style="font-size:1.15em;margin-right:3px;">+</span>Section</a>' + '</li>';
  } else {
    var addSection = '';
  }
  
  // Add preview and save buttons if we're editing
  if ((mw.config.get('wgAction') == 'edit') || (mw.config.get('wgAction') == 'submit')){
    var editButton = '<li class="buttonLi"><input class="button" form="editform" type="submit" value="Preview" name="wpPreview"></input></li>' +
      '<li class="buttonLi"><input class="button" form="editform" type="submit" value="Save" name="wpSave"></input></li>' +
      '<li><a href="' + pre + mw.config.get('wgPageName') + '&action=edit' + '"><img style="padding-right:5px;margin-bottom:3px;" src="' + imageEdit + '" height="17px" alt="">Edit</a>' + '</li>';
  } else {
    var editButton = '<li><a href="' + pre + mw.config.get('wgPageName') + '&action=edit' + '"><img style="padding-right:5px;margin-bottom:3px;" src="' + imageEdit + '" height="17px" alt="">Edit</a>' + '</li>';
  }
  
  // Leave out main/talk switch and history buttons on Special pages
  if (mw.config.get('wgNamespaceNumber') > -1){
    var switchButton = '<li><a href="' + pre + getAssoc('url') + '"><img style="padding-right:5px;margin-bottom:3px;opacity:0.9;" src="' + imageSwitch + '" height="15px" alt="">' + getAssoc('name') + '</a>' + '</li>';
    var historyButton = '<li><a href="' + pre + mw.config.get('wgPageName') + '&action=history' + '"><img style="padding-right:3px;margin-bottom:3px;" src="' + imageHistory + '" height="17px" alt="">History</a>' + '</li>';
  
  } else {
    var switchButton = '';
    var historyButton = '';
  }
  
  // Fill the Floater div with some crap
  floater.html(
    
    // Left section for page title, edit, history, and main/talk toggle
    '<div style="font-weight:bold;float:left;font-size:0.9em;">' + 
      '<ul class="floaterPagelinks" style="margin-left:10px;list-style-type:none;list-style-image:none;display:inline;">' +
        titleLine + 
        editButton +
        addSection +
        historyButton +
        switchButton +
      '</ul>' +
    '</div>' + 
    
    // Small links for info, logs, whatlinkshere
    '<div style="float:left;margin-top:-7px;margin-left:-15px;">' +
      '<ul class="smallLinks" style="list-style-type:disc;">' +
        '<li><a href="' + pre + mw.config.get('wgPageName') + '&action=info" title="Information for this page">I</a></li>' +
        '<li>|</li>' +
        '<li><a href="/wiki/Special:Log/' + mw.config.get('wgPageName') + '" title="Page logs">L</a></li>' +
        '<li>|</li>' +
        '<li><a href="/wiki/Special:WhatLinksHere/' + mw.config.get('wgPageName') + '" title="What Links Here">W</a></li>' +
        '<li>|</li>' +
        '<li><a class="gotoTop" href="#topTop" title="Go back to the top">Top</a></li>' +
      '</ul>' +
    '</div>' +
    
    // Search bar
    '<div style="float:right;margin-top:3px;font-size:.9em;">' + 
      '<form class="searchform" action="/w/index.php">' +
        '<div id="simpleSearch2" class="simpleSearch" style="margin-top:-4px;margin-bottom:-20px;margin-right: 25px;width:14em;">' +
          '<input id="searchInput2" class="mw-searchInput" placeholder="Search" name="search" tabindex="10" autocomplete="off" style="width:100%;"></input>' +
          '<button id="searchButton" name="button" type="submit" style="position: absolute;right: 0px;top: 0px;padding: 0.45em 0.4em 0.2em 0.3em;margin-right: 20px;border: medium none;cursor: pointer;background-color: transparent;background-image: none;">' + 
            '<img width="12" height="13" alt="Search" src="//bits.wikimedia.org/static-1.22wmf18/skins/vector/images/search-ltr.png?303-4"></img>' +
          '</button>' +
          '<input type="hidden" value="Special:Search" name="title"></input>' +
        '</div>' +
      '</form>' +
    '</div>' +
    
    // User links
    '<div style="float:right;font-size:.8em;font-weight:bold;margin-top:1px;">' + 
      '<ul class="floaterUserlinks" style="list-style-type:none;list-style-image:none;display:inline;margin-right:20px;">' +
        '<li class="floaterUserpageLink"><a title="Your user page" href = "/wiki/User:' + mw.config.get('wgUserName') + '">' + mw.config.get('wgUserName') + '</a></li>' + 
        //'<li><a class="mw-echo-notifications-badge" href="/wiki/Special:Notifications"></a></li>' +
        '<li><a title="Your talk page" href = "/wiki/User talk:' + mw.config.get('wgUserName') + '">' + 'Talk' + '</a></li>' +
        '<li><a title="Your preferences" href = "/wiki/Special:Preferences">' + 'Prefs' + '</a></li>' +
        '<li><a title="Go to your watchlist" href = "/wiki/Special:Watchlist">' + 'Watchlist' + '</a></li>' +
        '<li><a title="Display your contribution history" href = "/wiki/Special:Contributions/' + mw.config.get('wgUserName') + '">' + 'Contribs' + '</a></li>' +
        '<li id="utcdate2"><a title="Click to purge this page" href="' + pre + mw.config.get('wgPageName') + '&action=purge"></a></li>' +
      '</ul>' +
    '</div>'); 
  
  // Set the "go to top" click function: Go to the MediaWiki top anchor, then scroll up some more
  $('a.gotoTop').click(function(){
    window.location.hash="top"; 
    window.scrollBy(0, -floaterHeight - 50);
  });
  
  // Wait half a sec for images to load etc. b4 un-hiding Floater
  setTimeout(function(){floater.prop('hidden', false)},500);
  
  // Listen for TOC or other internal anchor clicks and adjust page scrolling to un-obscure the associated header
  $(window).on('hashchange', function(){
    adjustForHash();
  });
  
  // Run the scroll function once on load after additional half-second delay to display Floater in case we come in mid-page
  setTimeout(function(){
    scroll();
    adjustForHash();
  },500); 
  
  function adjustForHash(){
    // If we're coming in mid-page due to an anchor link, make sure the anchored header isn't obscured by Floater
    if (window.location.hash) {
      
      // Get DOM version of the anchored header using [0], then use DOM method to get its viewport coordinates
      var anchorCoords = $('[id="' + window.location.hash.replace('#','') + '"]:last')[0].getBoundingClientRect();
      
      // If the pagetop links aren't in view and the anchored header is likely obscured by Floater, scroll up to reveal it
      if (($('#p-namespaces ul li:above-the-top').length > 0) && (anchorCoords.bottom < 25)){
        window.scrollBy(0, -floaterHeight - 5);
      }
    }
  }
  
  // Set the function for scrolling
  $(window).scroll(function(){
    scroll();
  });
  
  // Use :above-the-top (from plugin below) to check for pagetop stuff outside window. If they're there, start the music.
  function scroll(){
    if ($('#p-namespaces ul li:above-the-top').length > 0){
      floater.css('top','0');
    } else {
      floater.css('top','-' + floaterHeight + 'px');
    }
  }
  
  // Find the title of the associated talk or main page. Is there an easier way?
  function getAssoc(type){
    var toggledTitle = '';
    var toggled = '';
    var ns = mw.config.get('wgNamespaceNumber');
    var title = mw.config.get('wgTitle');
    if (ns == 0){
      toggledTitle = "Talk:" + title;
      toggled = "Talk";
    } else if (ns == 1){
      toggledTitle = title;
      toggled = "Article";
    } else if (ns == 2){
      toggledTitle = "User_talk:" + title;
      toggled = "Talk";
    } else if (ns == 3){
      toggledTitle = "User:" + title;
      toggled = "User page";
    } else if (ns == 4){
      toggledTitle = "Wikipedia_talk:" + title;
      toggled = "Talk";
    } else if (ns == 5){
      toggledTitle = "Wikipedia:" + title;
      toggled = "Project page";
    } else if (ns == 6){
      toggledTitle = "File_talk:" + title;
      toggled = "Talk";
    } else if (ns == 7){
      toggledTitle = "File:" + title;
      toggled = "File page";
    } else if (ns == 8){
      toggledTitle = "MediaWiki_talk:" + title;
      toggled = "Talk";
    } else if (ns == 9){
      toggledTitle = "MediaWiki:" + title;
      toggled = "MediaWiki page";
    } else if (ns == 10){
      toggledTitle = "Template_talk:" + title;
      toggled = "Talk";
    } else if (ns == 11){
      toggledTitle = "Template:" + title;
      toggled = "Template page";
    } else if (ns == 12){
      toggledTitle = "Help_talk:" + title;
      toggled = "Talk";
    } else if (ns == 13){
      toggledTitle = "Help:" + title;
      toggled = "Help page";
    } else if (ns == 14){
      toggledTitle = "Category_talk:" + title;
      toggled = "Talk";
    } else if (ns == 15){
      toggledTitle = "Category" + title;
      toggled = "Cat page";
    } else if (ns == 16){
      toggledTitle = "Portal_talk:" + title;
      toggled = "Talk";
    } else if (ns == 17){
      toggledTitle = "Portal:" + title;
      toggled = "Portal page";
    }
    if (type == 'url'){
      var returned = toggledTitle;
    } else if (type == 'name'){
      var returned = toggled;
    }
    return returned;
  }
  
  // Add the :above-the-top jQuery selector, which we use to check if user has scrolled past a certain point.
  function loadJQViewport(){
    /* Excerpt from http://www.appelsiini.net/projects/viewport, Copyright (c) 2008-2009 Mika Tuupola, MIT license: http://www.opensource.org/licenses/mit-license.php
     $(":above-the-top") */
    (function($) {
      $.abovethetop = function(element, settings){
        var top = $(window).scrollTop();
        return top >= $(element).offset().top + $(element).height() - settings.threshold;
      };
      $.extend($.expr[':'], {
        "above-the-top": function(a, i, m) {
          return $.abovethetop(a, {threshold : 0});
        }
      });
    })(jQuery);
  }
  
  //If the clock gadget is enabled, replicate it for Floater
  if (mw.user.options.get('gadget-UTCLiveClock') == 1){
    var $target;
    function showTime($target){
      var dateNode = $('#utcdate2');
      if (!dateNode){return;}
      var now = new Date();
      var hh = now.getUTCHours();
      var mm = now.getUTCMinutes();
      var ss = now.getUTCSeconds();
      if ($target === undefined){$target = $(dateNode).find('a:first');}
      var time = ( hh < 10 ? '0' + hh : hh ) + 
        ':' + ( mm < 10 ? '0' + mm : mm ) + 
        ':' + ( ss < 10 ? '0' + ss : ss );
      $target.text(time);
            var ms = now.getUTCMilliseconds();
      setTimeout( function(){showTime($target); }, 1100 - ms);
    }
    showTime();
  }
  
  // The rest of this replicates the MediaWiki suggest functionality for Floater's search box
  var map2, resultRenderCache2, searchboxesSelectors2;
  var $searchInput2 = $('#searchInput2');
  var $searchRegion2 = $('#simpleSearch2');
  function computeResultRenderCache2(context){
    var $form, formAction, baseHref, linkParams;
    $form = context.config.$region.closest('form');
    formAction = $form.attr('action');
    baseHref = formAction + (formAction.match(/\?/) ? '&' : '?');
    linkParams = {};
    $.each( $form.serializeArray(), function (idx, obj){linkParams[obj.name] = obj.value;});
    return {textParam: context.data.$textbox.attr('name'), linkParams: linkParams, baseHref: baseHref};
  }
  function renderFunction2(text, context){
    if (!resultRenderCache2){resultRenderCache2 = computeResultRenderCache2(context);}
    resultRenderCache2.linkParams[resultRenderCache2.textParam] = text;
    this.append($('<span>').css('whiteSpace', 'nowrap').text(text)).wrap($('<a>')
      .attr('href', resultRenderCache2.baseHref + $.param( resultRenderCache2.linkParams)).addClass('mw-searchSuggest-link'));
  }
  searchboxesSelectors2 = ['#searchInput2'];
  $(searchboxesSelectors2.join(', ')).suggestions({fetch: function (query){
    var $el, jqXhr;
    if (query.length !== 0){
      $el = $(this);
      jqXhr = $.ajax({url: mw.util.wikiScript('api'),data: {format: 'json', action: 'opensearch', search: query, namespace: 0, suggest: ''},
        dataType: 'json', success: function (data){if ($.isArray(data) && data.length){$el.suggestions('suggestions', data[1]);}}});
      $el.data('request', jqXhr);
    }},
  cancel: function (){
    var jqXhr = $(this).data('request');
    if (jqXhr && $.isFunction(jqXhr.abort)){jqXhr.abort();$(this).removeData('request');
    }},result: {render: renderFunction2,select: function ($input){$input.closest('form').submit();}},
  delay: 120, highlightInput: true}).bind('paste cut drop', function (){$(this).trigger('keypress');});
  function specialrenderFunction2(query, context){
    var $el = this;
    if (!resultRenderCache2){resultRenderCache2 = computeResultRenderCache2(context);}
    resultRenderCache2.linkParams[resultRenderCache2.textParam] = query;
    if ($el.children().length === 0){
      $el.append($('<div>').addClass('special-label').text(mw.msg('searchsuggest-containing')), $('<div>').addClass('special-query').text(query).autoEllipsis()).show();
    } else {$el.find('.special-query').text(query).autoEllipsis();}
    if ($el.parent().hasClass('mw-searchSuggest-link')){
      $el.parent().attr('href', resultRenderCache2.baseHref + $.param(resultRenderCache2.linkParams) + '&fulltext=1');
    } else {$el.wrap($('<a>').attr('href', resultRenderCache2.baseHref + $.param(resultRenderCache2.linkParams) + '&fulltext=1').addClass('mw-searchSuggest-link'));}
  }
  $searchInput2.attr('placeholder', mw.msg('searchsuggest-search')).placeholder();
  $searchInput2.suggestions({result: {render: renderFunction2, select: function ($input){$input.closest('form').submit();}},
    special: {
      render: specialrenderFunction2, select: function ($input){$input.closest('form').append($('<input type="hidden" name="fulltext" value="1"/>'));
      $input.closest('form').submit();}}, $region: $searchRegion2});
});