MediaWiki:Gadget-AdvancedTooltip.js

From Oxygen Not Included Wiki
Jump to navigation Jump to search

Style changes not showing up

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)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.

Documentation [ view ] [ talk ]

This script is called by Template:ElementTooltip, and reads the data-* attributes on the <span>-element provided by the Lua Module ElementTooltip, and replaces the entire span with an infobox-like structure like shown in the collapsible codebox below.

example html of infobox-like structure
<div class="advanced-tooltip--content element-tooltip--content"">
    <h2>Copper</h2>
    <div class="element-tooltip--caption">
        (Cu) Copper is a conductive Metal. It is suitable for building Power systems.
    </div>

    <div class="element-tooltip--row">
        <div class="element-tooltip--label">
            Specific Heat Capacity
        </div>
        <div class="element-tooltip--data">
            0.385(DTU/g)/°C
        </div>
    </div>
    
    <div class="element-tooltip--row">
        <div class="element-tooltip--label">
            Thermal Conductivity
        </div>
        <div class="element-tooltip--data">
            60(DTU/(m*s))/°C
        </div>
    </div>

    <div class="element-tooltip--row">
        <div class="element-tooltip--label">
            Hardness
        </div>
        <div class="element-tooltip--data">
            25 (Firm)
        </div>
    </div>

    <div class="element-tooltip--row">
        <div class="element-tooltip--label">
            Max Mass
        </div>
        <div class="element-tooltip--data">
            3870kg
        </div>
    </div>
    
    <div class="element-tooltip--row">
        <div class="element-tooltip--label">
            at 1083.85°C melts into
        </div>
        <div class="element-tooltip--data">
            Liquid Copper(SHC: 0.386)
        </div>
    </div>
</div>

Syntax replacement

Captions and chemical symbols sometimes contain a subscript like CO2 as CO<sub>2</sub>. The lua script parses these as CO--2-- to be able to be housed into a data attribute. This needs to be rebuilt in javascript.

Javascript

// tooltip setup
var cursorOffset = { X:15, Y:20 };  // 0,0 means the tooltip topleft aligns with the tip of the cursor
var clearance = { X:5, Y:5 };       // 0,0 means the tooltip bottomright aligns with bottomright of the window.

function positionTooltip(e) {
    // get tooltip html element
    var $tooltip = $(e.currentTarget).hasClass("advanced-tooltip--content")
        ? $(e.currentTarget)
        : $(e.currentTarget).find(".advanced-tooltip--content");

    // calculate how much the tooltip would overflow at the edge of the window above the desired clearance
    var overflow = {
        right : e.clientX + $tooltip.outerWidth() + cursorOffset.X + clearance.X - $(window).width(),
        bottom : e.clientY + $tooltip.outerHeight() + cursorOffset.Y + clearance.Y - $(window).height()
    };
    
    // scope to which the tooltip is in relation to (first ancestor whose position is not static, usually #bodyContent)
    var scope = $tooltip.parents().filter(function() { return $(this).css('position') !== 'static'; }).first();
    // tooltip position = curserposition + offset, subtract overflow if necessary
    $tooltip.css({
        left: Math.round(e.pageX - scope.offset().left + cursorOffset.X - ((overflow.right > 0) ? overflow.right : 0)) + "px",
        top: Math.round(e.pageY - scope.offset().top + cursorOffset.Y - ((overflow.bottom > 0) ? overflow.bottom : 0)) + "px"
    });
}


function makeRow(data, label, formattedData) {
    if (data === undefined) { return ''; }
    return '<div class="element-tooltip--row" >' + 
        '<div class="element-tooltip--label" >' + label + '</div>' +
        '<div class="element-tooltip--data" >' + formattedData + '</div>' +
    '</div>';
}
function displayTemp(tempK) {
    return '<span class="temp-celsius">' + (parseFloat(tempK)-273.15).toFixed(2) + '&nbsp;°C</span>' + 
           '<span class="temp-fahrenheit">' + (1.8*(parseFloat(tempK))-459.67).toFixed(2) + '&nbsp;°F</span>';
}

var mathStrSHC = '<math class="mwe-math-element" xmlns="http://www.w3.org/1998/Math/MathML"><mstyle displaystyle="true" scriptlevel="0"><mrow data-mjx-texclass="ORD"><mstyle displaystyle="false" scriptlevel="0"><mrow data-mjx-texclass="ORD"><mfrac><mrow data-mjx-texclass="ORD"><mrow data-mjx-texclass="ORD"><mtext>DTU</mtext></mrow></mrow><mrow data-mjx-texclass="ORD"><mrow data-mjx-texclass="ORD"><mtext>g</mtext></mrow><msup><mstyle scriptlevel="0"><mspace width="0.167em"></mspace></mstyle><mrow data-mjx-texclass="ORD"><mo>∘</mo></mrow></msup><mrow data-mjx-texclass="ORD"><mtext>';
var mathStrTC  = '<math class="mwe-math-element" xmlns="http://www.w3.org/1998/Math/MathML"><mstyle displaystyle="true" scriptlevel="0"><mrow data-mjx-texclass="ORD"><mstyle displaystyle="false" scriptlevel="0"><mrow data-mjx-texclass="ORD"><mfrac><mrow data-mjx-texclass="ORD"><mrow data-mjx-texclass="ORD"><mtext>DTU</mtext></mrow></mrow><mrow data-mjx-texclass="ORD"><mrow data-mjx-texclass="ORD"><mtext>m</mtext></mrow><mstyle scriptlevel="0"><mspace width="0.167em"></mspace></mstyle><mrow data-mjx-texclass="ORD"><mtext>s</mtext></mrow><msup><mstyle scriptlevel="0"><mspace width="0.167em"></mspace></mstyle><mrow data-mjx-texclass="ORD"><mo>∘</mo></mrow></msup><mrow data-mjx-texclass="ORD"><mtext>';
var mathStrEnd = '</mtext></mrow></mrow></mfrac></mrow></mstyle></mrow></mstyle></math>';
function convertAndFormat(input) {
    return (5/9*parseFloat(String(input))).toFixed((String(input).split('.')[1] || '').length + 1);
}
function displaySHC(shc) {
    return '<span class="temp-celsius">' + shc + '&nbsp;' + mathStrSHC + 'C' + mathStrEnd + '</span>' + 
           '<span class="temp-fahrenheit">' + convertAndFormat(shc) + '&nbsp;' + mathStrSHC + 'F' + mathStrEnd + '</span>';
}
function displayTC(tc) {
    return '<span class="temp-celsius">' + tc + '&nbsp;' + mathStrTC + 'C' + mathStrEnd + '</span>' + 
           '<span class="temp-fahrenheit">' + convertAndFormat(tc) + '&nbsp;' + mathStrTC + 'F' + mathStrEnd + '</span>';
}

function makePhase(statedata) {
    if (statedata.name === undefined ) { return ''; }
    if (statedata.oreName === undefined ) {
        return '<div class="element-tooltip--row" >' + 
            '<div class="element-tooltip--label" >at ' + displayTemp(statedata.temp) + '&nbsp;' + statedata.change + '</div>' +
            '<div class="element-tooltip--data" >' + statedata.pic + statedata.name + ' (SHC: ' + displaySHC(statedata.SHC) + ')</div>' +
            '</div>';
    }
    return '<div class="element-tooltip--row" >' + 
        '<div class="element-tooltip--label" >at ' + (Math.round(100*(parseFloat(statedata.temp)-273.15))/100) + '°C ' + statedata.change + '</div>' +
        '<div class="element-tooltip--data" >' + 
        Math.round(100 - parseFloat(statedata.orePart)*100) + '% ' + statedata.pic + statedata.name + ' (SHC: ' + displaySHC(statedata.SHC) + ')<br>' +
            Math.round((statedata.orePart)*100) + '% ' + statedata.orePic + statedata.oreName + ' (SHC: ' + displaySHC(statedata.oreSHC) + ')</div>' +
        '</div>';
}

function hardFormat(num) {
    if (num < 5) { return num + " (Very Soft)"; } 
    else if (num < 10) { return num + " (Soft)"; } 
    else if (num < 25) { return num + " (Firm)"; } 
    else if (num < 80) { return num + " (Very Firm)"; } 
    else if (num < 250) { return num + " (Nearly Impenetrable)"; } 
    else { return num + " (Impenetrable)"; }
}

function fillElementTooltip($p) {
    var e = $p.find('.element-tooltip--content');
    var displayText = $p.find('a[title] span[title=""]').text();

    // e starts as a <span> but will be changed into a <div>

    // Fetch the data attributes
    // if any attribute is not found, they are undefined, not empty or nil
    var name = e.data('elementname');
    var caption;
    var chem;
    if (e.data('caption') !== undefined ) { caption = e.data('caption').replace(/--(.)--/g, "<sub>$1</sub>"); }
    if (e.data('chem') !== undefined ) { chem = e.data('chem').replace(/--(.)--/g, "<sub>$1</sub>"); }
    var SHC = e.data('specificheatcapacity');
    var TC = e.data('thermalconductivity');
    var hardness = e.data('hardness');
    var maxMass = e.data('maxmass');

    var highTemp = {
        temp    : e.data('hightemp'),       	                    // Transition Temp in K
        change  : e.data('hightemptransitionname'),                 // name of transition, e.g. "melts into", "sublimates into"
        name    : e.data('hightemptransitiontargetname'),
        SHC     : e.data('hightemptransitiontargetshc'),
        TC      : e.data('hightemptransitiontargettc'),
        pic     : '',
        orePart : e.data('hightemptransitionoremassconversion'),    // part of mass that gets turned into a different element from 0 to 1
        oreName : e.data('hightemptransitionoreidname'),            
        oreSHC  : e.data('hightemptransitionoreidshc'),
        oreTC   : e.data('hightemptransitionoreidtc'),
        orePic  : ''
    };

    var lowTemp = {
        temp    : e.data('lowtemp'),
        change  : e.data('lowtemptransitionname'),
        name    : e.data('lowtemptransitiontargetname'),
        SHC     : e.data('lowtemptransitiontargetshc'),
        TC      : e.data('lowtemptransitiontargettc'),
        pic     : '',
        orePart : e.data('lowtemptransitionoremassconversion'),
        oreName : e.data('lowtemptransitionoreidname'),
        oreSHC  : e.data('lowtemptransitionoreidshc'),
        oreTC   : e.data('lowtemptransitionoreidtc'),
        orePic  : ''
    };


    // Finding child elements correctly
    var children = e.find('.element-tooltip--related-pic');

    children.each(function() {
        var picof = $(this).data('picof');
        var htmlContent = $(this).html();

        if (picof === 'highTempTransitionTargetName') {
            highTemp.pic = htmlContent;
        } else if (picof === 'highTempTransitionOreIdName') {
            highTemp.orePic = htmlContent;
        } else if (picof === 'lowTempTransitionTargetName') {
            lowTemp.pic = htmlContent;
        } else if (picof === 'lowTempTransitionOreIdName') {
            lowTemp.orePic = htmlContent;
        }
    });

    var output = 
        '<div class="advanced-tooltip--content element-tooltip--content">' +
        ((name !== displayText) ? ('<h2>' + name + '</h2>') : '') +
        ( (caption != undefined) ? ('<div class="element-tooltip--caption"> ' + caption + ' </div>') : '') +
        makeRow(chem, 'Chemical Symbol', chem) +
        makeRow(SHC, 'Specific Heat Capacity', displaySHC(SHC)) + // + '(DTU/g)/°C') +
        makeRow(TC, 'Thermal Conductivity', displayTC(TC)) + // + '(DTU/(m*s))/°C') +
        makeRow(hardness, 'Hardness', hardFormat(hardness)) +
        makeRow(maxMass, 'Max Mass', maxMass + '&nbsp;kg') +
        makePhase(highTemp) +
        makePhase(lowTemp) +
        '</div>';

    $(e).replaceWith(output);
}

// fill content of every html elements of class "element-tooltip--content"
$(document).ready(function () {
	console.log('AdvancedTooltip initialized...');
    var atooltips = $('.advanced-tooltip');
    console.log(atooltips.length + ' AdvancedTooltip(s) found!');
    atooltips.on('mousemove', positionTooltip);
    console.log(atooltips.length + ' AdvancedTooltip(s) implemented!');

    var etooltip = $('.element-tooltip');
    console.log(etooltip.length + ' ElementTooltip(s) found!');
    etooltip.each(function(e) { fillElementTooltip($(this)); });
    console.log(etooltip.length + ' ElementTooltip(s) implemented!');
	console.log('AdvancedTooltip finished!');
});