User:Majr/common.js

/** * Creates minecraft style tooltips * * Replaces normal tooltips. Supports mcw:formatting codes (except k), * a description with line breaks ("/"), and character escaping with "\". */ ( function {	var $tooltip,		escapeChars = { '\\&': '&#38;', '<': '&#60;', '>': '&#62;' },		escape = function( text ) {			// "\" must be escaped first			return text.replace( /\\\\/g, '&#92;' )				.replace( /\\&|[<>]/g, function( char ) { return escapeChars[char]; } );		},		$win = $( window ), winWidth, winHeight, width, height,		supportsTransform = 'transform' in document.documentElement.style;	$( '#mw-content-text' ).on( { 'mouseenter.minetip': function( e ) { var $elem = $( this ), title = $elem.attr( 'data-minetip-title' ); // No title or title only contains formatting codes if ( title === undefined || title && title.replace( /&([0-9a-fl-o])|\s+/g,  ) ===  ) { // Find deepest child title var childElem = $elem[0], childTitle; do { if ( childElem.hasAttribute( 'title' ) ) { childTitle = childElem.title; }					childElem = childElem.firstChild; } while( childElem && childElem.nodeType === 1 ); if ( childTitle === undefined ) { return; }				// Append child title as title may contain formatting codes if ( !title ) { title = ''; }				title += childTitle; // Set the retrieved title as data for future use $elem.attr( 'data-minetip-title', title ); }			if ( !$elem.data( 'minetip-ready' ) ) { // Remove title attributes so the native tooltip doesn't get in the way $elem.find( '[title]' ).addBack.removeAttr( 'title' ); $elem.data( 'minetip-ready', true ); }			if ( title === '' ) { return; }			// Apply normal escaping title = escape( title ); var text = ' ' + title + '&f '; var description = $elem.attr( 'data-minetip-text' ); if ( description ) { // Apply normal escaping plus "/" description = escape( description ).replace( /\\\//g, '&#47;' ); text += ' ' + description.replace( /\//g, ' ' ) + '&f '; }			// Add classes for minecraft formatting codes while ( /&[0-9a-el-o]/.test( text ) ) { text = text.replace( /&([0-9a-el-o])(.*?)(&f|$)/g, '$2 &f' ); }			// Remove reset formatting text = text.replace( /&f/g, '' ); // Unescape "&" so HTML entities work text = text.replace( /&#38;/g, '&' ); $tooltip = $( '#minetip-tooltip' ); if ( !$tooltip.length ) { $tooltip = $( ' ' ).appendTo( 'body' ); }			$tooltip.html( text ); // Cache current window and tooltip size winWidth = $win.width; winHeight = $win.height; width = $tooltip.outerWidth( true ); height = $tooltip.outerHeight( true ); // Trigger a mouse movement to position the tooltip $elem.trigger( 'mousemove', e ); },		'mousemove.minetip': function( e, trigger ) { if ( !$( '#minetip-tooltip' ).length ) { $( this ).trigger( 'mouseenter' ); return; }			// Get event data from remote trigger e = trigger || e;			// Get mouse position and add default offsets var top = e.clientY - 34, left = e.clientX + 14; // If going off the right of the screen, go to the left of the cursor if ( left + width > winWidth ) { left -= width + 36; }			// If now going off to the left of the screen, resort to going above the cursor if ( left < 0 ) { left = 0; top -= height - 22; // Go below the cursor if too high if ( top < 0 ) { top += height + 47; }			// Don't go off the top of the screen } else if ( top < 0 ) { top = 0; // Don't go off the bottom of the screen } else if ( top + height > winHeight ) { top = winHeight - height; }			// Apply the positions if ( supportsTransform ) { $tooltip.css( 'transform', 'translate(' + left + 'px, ' + top + 'px)' ); } else { $tooltip.css( { top: top, left: left } ); }		},		'mouseleave.minetip': function { if ( !$tooltip ) { return; }			$tooltip.remove; }	}, '.minetip, .grid' ); } );