MediaWiki:FloatingToc/code.js

/** * TODO: * * - lots of general cleanup and optimizations... * - code uses a lot of classes that are generic to jQuery UI *  which will cause conflicts if similar widgets are on the page * - expanding and collapsing the bottom toolbar does not modify *  the draggable constraint */

(function {    var colorDefer = $.getScript('//dev.wikia.com/wiki/Colors.js');    var loaderDefer = $.Deferred;    mw.loader.using(['jquery.ui.dialog', 'jquery.effects.clip'], loaderDefer.resolve);    var pageDefer = $.Deferred;    $(pageDefer.resolve);    return $.when(loaderDefer, pageDefer, colorDefer) }) .done(function {    var toc = $('table#toc');    if (!toc.length) return;    var iconsWhite      = '//images.wikia.com/dev/images/c/c2/Ui-icons_ffffff_256x240.png',        iconsBlack      = '//images.wikia.com/dev/images/a/aa/Ui-icons_222222_256x240.png',        iconsLightGray  = '//images.wikia.com/dev/images/4/48/Ui-icons_cccccc_256x240.png',        iconsDarkGray   = '//images.wikia.com/dev/images/8/89/Ui-icons_666666_256x240.png',        pageBright = dev.colors.isBright(dev.colors.page),        menuBright = dev.colors.isBright(dev.colors.menu),        dialogTop;    var styles = '#tocDialog.toc ul ul {' +        'margin: 0 0 0 2em;' +    '} #tocDialog {' +        'margin-top: 0;' +        'border: none !important;' +        'left: auto; right: auto; top: auto; bottom: auto;' +        'height: auto; width: auto;' +        'float: none !important' +    '} .ui-dialog {' +        'border: 2px solid $border;' + '} .ui-corner-all {' + 'border-radius: 6px 6px 6px 6px;' + '} .ui-dialog-titlebar, #open-toc-win.ui-state-hover {' + 'background: $menu;' + 'background: -moz-linear-gradient(top, $gradient 35%, $menu 65%);' + 'background: -webkit-gradient(linear, left top, left bottom, color-stop(35%,$gradient), color-stop(65%,$menu));' + 'background: -webkit-linear-gradient(top, $gradient 35%,$menu 65%);' + 'background: -o-linear-gradient(top, $gradient 35%,$menu 65%);' + 'background: -ms-linear-gradient(top, $gradient 35%,$menu 65%);' + 'background: linear-gradient(to bottom, $gradient 35%,$menu 65%);' + 'filter: progid:DXImageTransform.Microsoft.gradient( startColorstr="$gradient", endColorstr="$menu",GradientType=0 );' + '} #open-toc-win.ui-state-hover {' + 'border: 1px solid ' + (pageBright ? '#CCCCCC' : '#666666') + ';' + '} .ui-dialog .ui-dialog-titlebar {' + 'border: 1px solid $menu;' + 'color: $contrast;' + 'font-weight: normal;' + 'padding: 0.25em 1em;' + '} .ui-dialog, .ui-dialog .toc {' + 'background-color: $page;' + 'color $text;' + '} #toc-back {' + 'background: transparent;' + 'border: none;' + 'height: 20px;' + 'position: absolute;' + 'right: 25px;' + 'top: 2px;' + 'width: 22px;' + '} #tocDialog a {' + 'color: $link;' + '} #open-toc-win {' + 'background: transparent;' + 'border: 1px solid ' + (pageBright ? '#CCCCCC' : '#666666') + ';' + '} .ui-widget-content .ui-icon {' + 'background-image: url("' + (menuBright ? iconsDarkGray : iconsLightGray) + '");' + '} #open-toc-win .ui-icon {' + 'background-image: url("' + (pageBright ? iconsLightGray : iconsDarkGray) + '");' + '} #open-toc-win.ui-state-hover .ui-icon, .ui-dialog-titlebar .ui-icon {' + 'background-image: url("' + (menuBright ? iconsBlack : iconsWhite) + '");' + '} .ui-dialog-titlebar-close.ui-state-hover, #toc-back.ui-state-hover {' + 'background: $contrast;' + 'background: -moz-linear-gradient(top, $menu 35%, $gradient 65%);' + 'background: -webkit-gradient(linear, left top, left bottom, color-stop(35%,$menu), color-stop(65%,$gradient));' + 'background: -webkit-linear-gradient(top, $menu 35%, $gradient 65%);' + 'background: -o-linear-gradient(top, $menu 35%, $gradient 65%);' + 'background: -ms-linear-gradient(top, $menu 35%, $gradient 65%);' + 'background: linear-gradient(to bottom, $menu 35%, $gradient 65%);' + 'filter: progid:DXImageTransform.Microsoft.gradient( startColorstr="$menu", endColorstr="$gradient",GradientType=0 );' + 'border: 1px solid $gradient;' + '}';   $('#tocStyles').remove; $(document.head).append(       '' +        '' + dev.colors.replace(styles) + ' '    ); var tocTitle = $('#toctitle'), titleWidth = 0; $('#toctitle').children.each(function { titleWidth += $(this).width; }); if (toc.width < titleWidth + 30) { tocTitle.css('padding-left', '30px'); }   var tocTop = toc.offset.top, tocHeight = toc.height; console.log('heights: ', tocHeight, $(window).height, Math.min(tocHeight + 20, $(window).height - 100)); var tocOffscreen = $('#toc').offset.top + $('#toc').height > $(window).scrollTop + $(window).height; var position = tocOffscreen ? { my: 'center', at: 'center', of: window } : { my: 'center', at: 'center', of: toc }; var openToc = $(' ') .appendTo(document.body) .css({       position: 'absolute',        left: toc.width + toc.offset.left - 18 + 'px',        top: $('#toctitle').offset.top  + 'px',        width: '22px',        zIndex: '1000'    }) .button({       icons: {            primary: "ui-icon-newwin"        },        text: false    }) .click(function {        $('#tocDialog').remove;        var dialog = $(' ' + toc.find('ul:first').html + ' ')        .appendTo('#WikiaArticle')        .dialog({ position: position, drag: function { dialogTop = parseInt(dialog.css('top'), 10) - $(window).scrollTop; },           close: function  { location.href = '#toc'; toc.css('display', 'table'); openToc.css('display', 'block'); if ($(window).scrollTop > tocTop) { if (tocTop + tocHeight < $(window).height) { $(window).scrollTop(0); } else { $(window).scrollTop(tocTop - 20); }               }                toc.find('ul:first').slideDown(300); },           create: function  { var close = $('.ui-dialog-titlebar-close') .attr('title', 'close'); $(' ') .insertBefore(close) .button({                   icons: {                        primary: 'ui-icon-arrowthickstop-1-n'                    },                    text: false                }) .attr('title', 'back to top') .click(function {                   location.href = '#';                    $(window).scrollTop(0);                }); },           open: function (event, ui) { $(this).parent.queue(function {                    dialogTop = parseInt(dialog.css('top'), 10) - $(window).scrollTop;                    $(this).draggable({ containment: [ 10,                           Math.max($('#WikiHeader').offset.top, $(window).scrollTop + 10), $(window).width - $(this).width - 20, $(window).scrollTop + $(window).height - $(this).height - ($('#WikiaBarWrapper').hasClass('hidden') ? 20 : 40) ],                       scroll: false });               });            },            resizeStop: function  { var scrollTop = $(window).scrollTop; dialog.draggable({                   containment: [                        10,                        Math.max($('#WikiHeader').offset.top, scrollTop + 10),                        $(window).width - dialog.width - 20,                        scrollTop + $(window).height - dialog.height - ($('#WikiaBarWrapper').hasClass('hidden') ? 20 : 40)                   ],                    scroll: false                }); },           show: { effect: 'clip', duration: 300 },           width: toc.width + 20 + 'px', height: Math.min(tocHeight + 20, $(window).height - 100) })       .parent;        toc.find('ul:first').slideUp(300, function { toc.css('display', 'none'); openToc.css('display', 'none'); });       $(window).scroll(function  { var scrollTop = $(window).scrollTop; dialog.draggable({               containment: [                    10,                    Math.max($('#WikiHeader').offset.top, scrollTop + 10),                    $(window).width - dialog.width - 20,                    //Math.min($(document).height - 20, scrollTop + $(window).height) - dialog.height - 20                    scrollTop + $(window).height - dialog.height - ($('#WikiaBarWrapper').hasClass('hidden') ? 20 : 40)               ],                scroll: false            }); dialog.css('top', Math.max(55, scrollTop + dialogTop) + 'px'); });       $(window).resize(function  { dialog.dialog('option', 'maxHeight', $(window).height - 100); dialog.css('height', Math.max(parseInt(dialog.css('height'), 10), toc.height + 40) + 'px'); });   }); });