User:Jeblad/common.js

From mediawiki.org

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.
console.log('inside common.js' );
// keep the previous position, marging, padding, and border
// as this is only a single element there is no need for a more involved structure
var previousLeft;
var previousMarginLeft;
var previousPaddingLeft;
var previousBorderLeft;
var $previousElevated = $([]);

// helper for testing whether set is empty
var isEmpty = function( $elements ) {
	console.log('isEmpty: ', $elements.length );
	return $elements.length === 0;
};

// helper for testing whether set is good
var isGood = function( $elements ) {
	$grandParents = jQuery.merge(
		$elements.parent( '.mw-parser-output' ).parent( '#mw-content-text' ),
		$elements.parent( 'dl, ul, ol' ).parent( '.mw-parser-output' ).parent( '#mw-content-text' ) );
	console.log('isGood: ', $elements.length );
	return $grandParents.length !== 0;
};

// helper to set position
// ie. this has side effects
var update = function( $elevated ) {
console.log('inside update' );
	// calculate the left offset
	var offsetLeft = $elevated.offset().left - mw.util.$content.offset().left;
	console.log('offset: ', offsetLeft );
	// dispatch on tag name
	switch ( $elevated.prop( 'tagName' ).toLowerCase() ) {
		case 'dt':
		case 'p':
			// keep for later
			previousLeft = null;
			previousMarginLeft = $elevated.css('margin-left');
			previousPaddingLeft = $elevated.css('padding-left');
			previousBorderLeft = $elevated.css('border-left');
			// adjust
			$elevated.css('margin-left', 'calc(-'+offsetLeft+'px + 0.4px)');
			$elevated.css('padding-left', 'calc('+offsetLeft+'px - 0.4px - 0.18rem)');
			$elevated.css('border-left', '0.18rem solid #0645ad');
			break;
		case 'h1':
		case 'h2':
		case 'h3':
		case 'h4':
		case 'h5':
		case 'h6':
			$before = $elevated.children('::before');
	console.log('before: ', $before.length );
			// keep for later
			previousLeft = $before.css('margin-left');
			previousMarginLeft = null;
			previousPaddingLeft = null;
			previousBorderLeft = $before.css('border-left');
			// adjust
			$before.css('left', 'calc(-'+offsetLeft+'px + 0.4px)');
			$before.css('border-left', '0.18rem solid #0645ad');
			break;
	}
	// keep for later
	$previousElevated = $elevated;
};

var addMarker = function() {
	console.log('inside on load' );
	// get parent block
	var $elevated = $(':target').closest('h1,h2,h3,h4,h5,h6,p,dt,dd,li,[style*="display:block"],[style*="display:block"]');
	// early return on empty set
	if ( isEmpty( $elevated ) ) {
		return;
	}
	// early return on hard to handle cases
	// ie. cases where target is inside nested blocks
	if ( !isGood( $elevated ) ) {
		return;
	}
	// add class for non-positional styling
	$elevated.addClass('mw-elevated-target');
	// update the position
	update( $elevated );
};

// this is done during the initial load
$(window).on('load', addMarker);

var moveMarker = function() {
	console.log('inside on hashchange' );
	// reset old values
	if ( $previousElevated.length !== 0 ) {
		if ( previousLeft !== null ) $previousElevated.css( 'left', previousLeft );
		if ( previousMarginLeft !== null ) $previousElevated.css( 'margin-left', previousMarginLeft );
		if ( previousPaddingLeft !== null ) $previousElevated.css( 'padding-left', previousPaddingLeft );
		if ( previousBorderLeft !== null ) $previousElevated.css( 'border-left', previousBorderLeft );
	}
	// remove class for non-positional styling
	if ( $previousElevated.length !== 0 ) {
		$previousElevated.removeClass('mw-elevated-target');
	}
	// get parent block
	$elevated = $(':target').closest('h1,h2,h3,h4,h5,h6,p,dt,dd,li,[style*="display:block"],[style*="display:block"]');
	// early return on empty set
	if ( isEmpty( $elevated ) ) {
		return;
	}
	// early return on hard to handle cases
	// ie. cases where target is inside nested blocks
	if ( !isGood( $elevated ) ) {
		return;
	}
	// add class for non-positional styling
	$elevated.addClass('mw-elevated-target');
	// update the position
	update( $elevated );
};

// this is done when the fragment changes without a new load being triggered
$(window).on('hashchange', moveMarker);

// this is done when the window size changes
$(window).on('resize', moveMarker);