User:FR30799386/Floater.js

// //Fork of User:Equazcion/Floater, resolving errors mw.loader.using(['mediawiki.util', 'mediawiki.user', 'mediawiki.storage','jquery.suggestions'], function {   var imageHistory, imageEdit, imageSwitch;    // Load prerequisites    var load;    if (mw.storage.get('floaterConfig') === 'legacy' || window.floaterConfig === 'legacy') {        imageHistory = "//upload.wikimedia.org/wikipedia/commons/a/ab/OOjs_UI_icon_history-invert.svg";        imageEdit = "//upload.wikimedia.org/wikipedia/commons/0/00/OOjs_UI_icon_edit-ltr-invert.svg";        imageSwitch = "//upload.wikimedia.org/wikipedia/commons/e/e8/Play_blauw.png";

load = mw.loader.load('/w/index.php?title=User:Equazcion/Floater.css&action=raw&ctype=text/css', 'text/css'); } else if (mw.storage.get('floaterConfig') === 'lite' || window.floaterConfig === 'lite') { imageHistory = "//upload.wikimedia.org/wikipedia/commons/a/ab/OOjs_UI_icon_history-invert.svg"; imageEdit = "//upload.wikimedia.org/wikipedia/commons/0/00/OOjs_UI_icon_edit-ltr-invert.svg"; imageSwitch = "//upload.wikimedia.org/wikipedia/commons/e/e8/Play_blauw.png"; load = mw.loader.load('/w/index.php?title=User:Zhaofeng Li/Floater.css&action=raw&ctype=text/css', 'text/css'); } else if (mw.storage.get('floaterConfig') === 'normal' || window.floaterConfig === 'normal') { imageHistory = "//upload.wikimedia.org/wikipedia/commons/2/27/OOjs_UI_icon_history.svg"; imageEdit = "//upload.wikimedia.org/wikipedia/commons/8/8a/OOjs_UI_icon_edit-ltr.svg"; imageSwitch = "//upload.wikimedia.org/wikipedia/commons/e/e8/Play_blauw.png";

load = mw.loader.load('/w/index.php?title=User:FR30799386/Floater.css&action=raw&ctype=text/css', 'text/css'); } else //fallback {       imageHistory = "//upload.wikimedia.org/wikipedia/commons/2/27/OOjs_UI_icon_history.svg"; imageEdit = "//upload.wikimedia.org/wikipedia/commons/8/8a/OOjs_UI_icon_edit-ltr.svg"; imageSwitch = "//upload.wikimedia.org/wikipedia/commons/e/e8/Play_blauw.png"; load = mw.loader.load('/w/index.php?title=User:FR30799386/Floater.css&action=raw&ctype=text/css', 'text/css'); }   $.when(load).done(function {        loadJQViewport;

// Predict a static floater height var floaterHeight = 31;

// Create/insert empty Floater div $('#mw-head').prepend('. ');

// Grab the div var floater = $('.floater'); floater.hide; var editButton, histroyButton, switchButton, addSection, pageTitle, titleLine; // 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') + ':'; }           pageTitle = pageNS + mw.config.get('wgTitle').substr(0, 7) + '...' + mw.config.get('wgTitle').substr(-15); titleLine = '' + pageTitle.replace(/_/g, ' ') + ' '; } else { titleLine = '' + mw.config.get('wgPageName').replace(/_/g, ' ') + ''; }

// If the current page has an "add section" tab, construct a link if ($('#ca-addsection').length > 0) { addSection = ' + Section' + ''; } else { addSection = ''; }

// Leave out main/talk edit switch and history buttons on Special pages if (mw.config.get('wgNamespaceNumber') > -1) { // Add preview and save buttons if we're editing if ((mw.config.get('wgAction') == 'edit') || (mw.config.get('wgAction') == 'submit')) { editButton = '  ' + ' ' + '<li><a href="' + mw.util.getUrl(mw.config.get('wgPageName'), {                       action: 'edit'                    }) + '"><img style="padding-right:5px;margin-bottom:3px;" src="' + imageEdit + '" height="17px" alt="">Edit</a>' + '</li>'; } else { editButton = '<li><a href="' + mw.util.getUrl(mw.config.get('wgPageName'), {                   action: 'edit'                }) + '"><img style="padding-right:5px;margin-bottom:3px;" src="' + imageEdit + '" height="17px" alt="">Edit</a>' + '</li>'; }           switchButton = '<li><a href="' + mw.util.getUrl(getAssoc('url')) + '"><img style="padding-right:5px;margin-bottom:3px;opacity:0.9;" src="' + imageSwitch + '" height="15px" alt="">' + getAssoc('name') + '</a>' + '</li>'; historyButton = '<li><a href="' + mw.util.getUrl(mw.config.get('wgPageName'), {               action: 'history'            }) + '"><img style="padding-right:3px;margin-bottom:3px;" src="' + imageHistory + '" height="17px" alt="">History</a>' + '</li>';

} else { editButton = ''; switchButton = ''; historyButton = ''; }

// Fill the Floater div with some crap floater.html(           ' <a href="javascript:void(0)" class="floater-close"> X </a> ' +            // Left section for page title, edit, history, and main/talk toggle            ' ' +            '<ul class="floaterPagelinks" style="margin-left:10px;list-style-type:none;list-style-image:none;display:inline;">' +            titleLine +            editButton +            addSection +            historyButton +            switchButton +            '</ul>' +            ' ' +

// Small links for info, logs, whatlinkshere ' ' +           '<ul class="smallLinks" style="list-style-type:disc;">' + '<li><a href="' + mw.util.getUrl(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="#top" title="Go back to the top">Top</a></li>' + '</ul>' + ' ' +

// Search bar ' ' +           '<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%;"> ' + '<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: 30px;border: medium none;cursor: pointer;background-color: transparent;background-image: none;">' + '<img width="12" height="13" alt="Search" src="//upload.wikimedia.org/wikipedia/commons/7/7e/Vector_search_icon.svg"> ' + ' ' +           '<input type="hidden" value="Special:Search" name="title"> ' + ' ' +           ' ' +            ' ' +

// User links ' ' +           '<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>' + ' <a title="Click to purge this page" href="' + mw.util.getUrl(mw.config.get('wgPageName'), {               action: 'purge'            }) + '"></a></li>' + '</ul>' + ' ');

// 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.show;        }, 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 if (typeof $('[id="' + window.location.hash.replace('#', '') + '"]:last')[0] !== 'undefined') { 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.pseudos, { "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($(' ').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        }).on('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($(' ').addClass('special-label').text(mw.msg('searchsuggest-containing')), $(' ').addClass('special-query').text(query).css('text-overflow', 'ellipsis')).show; } else { $el.find('.special-query').text(query).css('text-overflow', 'ellipsis'); }           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')); $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        }); $('.floater-close').click(function(e) {           e.preventDefault;            floater.css('display', 'none');        }); }); });