MediaWiki:Map/code.js

/* Adds visual WoW map and mapping constructs to the wiki pages. */

/**************************************************************************************

loaded after MW / Oasis, 'Common' and 'Wikia', will be loaded via import as 'load.php' which appears at the *bottom* of the page.
 * This 'MediaWiki:MapLightbox/code.js' is included by MediaWiki:Common.js, and is


 * All files will be checked and minified nearly the same.



/*jshint multistr:true, jquery:true, browser:true, devel:true, camelcase:true, curly:false, undef:true, unused:true, bitwise:true, eqeqeq:true, forin:true, immed:true, latedef:true, newcap:true, noarg:true, unused:true, regexp:true, strict:true, trailing:true */ /*global mediaWiki:true*/

(function (mw, $, window, document) {

'use strict';

// this module needs lots of CSS and all of it is in MediaWiki:Wikia.css (for now) if ('oasis' !== mw.config.get('skin')) return;

if (window.sessionStorage && window.sessionStorage.getItem('noMapLightbox')) return;

var MAP_ICONS = '//images3.wikia.nocookie.net/__cb1/wowwiki/images/f/f3/Map-sprites.png', LEGEND_BG = '//images1.wikia.nocookie.net/__cb1/wowwiki/images/5/50/Map-legend-bg.jpg', ABOUT_NOTES = '/Template:Zone_Map_Note',

MAP_MAX_WIDTH  = 1002, MAP_MAX_HEIGHT =  668, MAP_MIN_WIDTH  =   50,

COLUMN_WIDTH   =  240, COLUMN_PADDING =    6,

HEADER_HEIGHT  =   15, HEADER_PADDING =    4,

MARGIN_INNER   =   10, MARGIN_VERTICAL =  15, MARGIN_HORIZONTAL = 25,

LEGEND_PADDING =   10,

MIN_SCALE      =   50,

STOP_WORD_REGEX = /^\s*(?:a|the)\s+(.*)/i;

function initMaps ($maps) {

var n = 0;

var log = (window.console && window.sessionStorage &&     window.sessionStorage.getItem('debugMapLightbox') && function  {        var args = Array.prototype.slice.call(arguments);        args.unshift('MapLightbox: ');        return window.console.log.apply(window.console, args);      }) || $.noop;

var callbacks = { close:  $.Callbacks('unique'), enable: $.Callbacks('unique'), disable: $.Callbacks('unique'), refresh: $.Callbacks('unique'), resize: $.Callbacks('unique') };

var preloader = {

imgDefers: {}, img: function (src) { if (!preloader.imgDefers[src]) { var defer = $.Deferred, img = new Image; img.src = src; img.onload = defer.resolve; preloader.imgDefers[src] = { defer: defer, img: img };       }        return preloader.imgDefers[src].defer.promise; },

cancel: function (src) { delete preloader.imgDefers[src]; },

tipsy: function { var defer = $.Deferred; mw.loader.using('jquery.tipsy', defer.resolve); return defer.promise; }   };

function SortedObject (obj) { this.keys = []; for (var i in obj) { if (obj.hasOwnProperty(i)) { this.keys.push(i); }     }      this.keys.sort(this.compare); this.obj = obj; this.walker = -1; }

$.extend(SortedObject.prototype, {

compare: function (a, b) { /*jshint camelcase:false*/ var m_a = a.match(STOP_WORD_REGEX), m_b = b.match(STOP_WORD_REGEX); a = m_a ? m_a[1] : a;       b = m_b ? m_b[1] : b;       return a > b ? 1 : (a < b ? -1 : 0); },

reset: function { this.walker = -1; },

next: function { return ++this.walker < this.keys.length; },

key: function { return this.keys[this.walker]; },

val: function { return this.obj[this.keys[this.walker]]; }   });

var tips = {

gravity: function { var $icon = $(this), w = $icon.parent.width, offset = w / 100 * $icon.data('x'); return offset > 200 ? (offset < w - 200 ? 's' : 'se') : 'sw'; },

add: function ($icons, trigger, autoShow) { $icons .tipsy({         delayIn: 50,          opacity: 1,          trigger: trigger,          fade: true,          gravity: tips.gravity        }); if (autoShow && $icons.length) { $icons.tipsy('show'); tips.close = function { $icons.tipsy('hide'); callbacks.close.remove(tips.close); delete tips.close; };         callbacks.close.add(tips.close); } else if (trigger === 'manual') { $icons .mouseenter(tips.show) .mouseleave(tips.hide); }     },

show: function { $(this).tipsy('show'); },

hide: function { $(this).tipsy('hide'); }   };

var blackOut = {

$blackOut: false,

create: function { log('blackOut.create'); var defer = $.Deferred;

this.$blackOut = $(' ') .addClass('map-blackout') .css({         width:  $(document).width  + 'px',          height: $(document).height + 'px',          display: 'none'        }) .appendTo(document.body) .fadeIn(200, function {

$('html').css('overflow', 'hidden'); blackOut.refresh;

blackOut.$blackOut.click(callbacks.close.fire);

callbacks.refresh.add(blackOut.refresh); callbacks.close.add(blackOut.close);

defer.resolve; });       return defer.promise;      },

refresh: function { if (blackOut.$blackOut && blackOut.$blackOut.length) { blackOut.$blackOut .css({           width:  $(document).width  + 'px',            height: $(document).height + 'px'          }); }     },

close: function { log('blackOut.close'); if (blackOut.$blackOut && blackOut.$blackOut.length) {

$('html').css('overflow', 'auto');

callbacks.refresh.remove(blackOut.refresh); callbacks.close.remove(blackOut.close);

blackOut.$blackOut .off('click') .stop.fadeOut(100, function {            blackOut.$blackOut.remove;            blackOut.$blackOut = false;          }); }     }    };

function Map {}

$.extend(Map.prototype, {

init: function ($map, editLink, $icons, autoShow) { var largeSrc = $map.data('large'), file = 'File:' + largeSrc.split('/').pop, href = mw.config.get('wgArticlePath').replace(/\$1/, file);

this.src = $map.data('small'); this.$map = $map;

this.mapLightbox = new MapLightbox({         src: largeSrc,          zone: $map.data('zone'),          editLink: editLink,          file: file,          href: href,          $icons: $icons,          autoShow: autoShow        });

this.callbacks = { enable: $.proxy(this.enable, this), disable: $.proxy(this.disable, this) };

callbacks.enable.add(this.callbacks.enable); callbacks.disable.add(this.callbacks.disable); },

openLightbox: function { log('Map.openLightbox');

var $this = $(this), largeSrc = $this.data('large'), that = $this.data('map'),

legendPromise  = preloader.img(LEGEND_BG), largeSrcPromise = preloader.img(largeSrc);

blackOut.create .done(function {          $.when( legendPromise, largeSrcPromise, that.mapLightbox.prepare )         .done(function  { that.mapLightbox.init; });       });      },

enable: function { log('Map.enable'); this.$map .removeClass('map-disabled') .off('click') .attr('title', 'click to enlarge') .click(this.openLightbox);

callbacks.enable.remove(this.callbacks.enable); callbacks.disable.add(this.callbacks.disable); },

disable: function { log('Map.disable'); this.$map .addClass('map-disabled') .attr('title', '(window too small to show map)') .off('click');

callbacks.disable.remove(this.callbacks.disable); callbacks.enable.add(this.callbacks.enable); },

createMap: function { log('Map.createMap'); var $this = $(this), that = $this.data('map'), w = $this.data('size'), h = Math.round(w * 2 / 3), promise = preloader.img(that.src), pending = promise.state === 'pending', blip = that.x || that.y,         content, id;

if (blip && pending) { promise = $.when(           preloader.img(MAP_ICONS),            promise          ); }

content = ' '; content += ''; if (blip) { content += ' '; }       content += ' ';

if (pending) { id = 'hm' + (n++);

promise .done(function {            $('#'+id).replaceWith(content);          });

return ' '; }

return content; },

gravity: function { var $this = $(this), top = $this.offset.top, h = Math.round($this.data('size') * 2 / 3); return top - h - 20 < $(window).scrollTop ? 'nw' : 'sw'; },

addTipsy: function { log('Map.addTipsy'); this.$map .tipsy({         delayIn: 50,          opacity: '1.0',          html: true,          fade: true,          trigger: 'manual',          gravity: this.gravity,          title: this.createMap        }) .on('mouseover mouseenter', function {          if (!$(document.body).hasClass('map-tipsy')) {            $(this).tipsy('show');            $(document.body).addClass('map-tipsy');          }        }) .on('mouseleave click', function {          $(this).tipsy('hide');          $(document.body).removeClass('map-tipsy');        }); }   });

function Coords ($map) { var $a = $map.find('a'), that = this, $icon;

this.x = $map.data('x'); this.y = $map.data('y'); this.iconTitle = '[' + this.x + ',' + this.y + ']';

if ($a.length) { $map.find('sup').unwrap; }

$map.addClass('map-preload');

$icon = $(' ', {        'data-x': this.x,        'data-y': this.y,        'data-icon': 'Blip',        'data-note': 'mn0',        'title': this.iconTitle,        'original-title': this.iconTitle      }) .css({       left: this.x + '%',        top:  this.y + '%'      }) .addClass('map-Icon map-Blip');

this.init($map, false, $icon, true);

preloader.tipsy .done(function {        that.addTipsy;      }); }

Coords.prototype = new Map;

function Link ($map) { var $a = $map.find('a'), that = this;

if ($a.length) { $map.text($a.text); }

this.init($map, false, false, false);

preloader.tipsy .done(function {        that.addTipsy;      });

}

Link.prototype = new Map;

function Embedded ($map) {

var smallSrc = $map.data('small'), $icons = $map.find('.map-Icon,.map-POI');

if (!$icons.length) $icons = false;

this.init($map, this.findEditLink($map), $icons, false);

$map .find('> a > img') .unwrap;

if ($icons) { $map .addClass('map-preload'); $.when(         preloader.img(MAP_ICONS),          preloader.tipsy,          preloader.img(smallSrc)        ) .done(function {          $map          .removeClass('map-preload');          tips.add($icons, 'hover');        }); } else { $map .removeClass('map-preload'); }   }

Embedded.prototype = new Map;

$.extend(Embedded.prototype, {

findEditLink: function ($map) { var $walker = $map, $prev, $h = false, $top = $('#mw-content-text'); while (!$walker.is($top)) { if (/^h\d$/i.test($walker[0].nodeName)) { $h = $walker; break; }         $prev = $walker.prev; $walker = $prev.length ? $prev : $walker.parent; }       if (!mw.config.get('wgUserName')) { return '/Special:SignUp?returnto=' + mw.util.wikiUrlencode(             mw.config.get('wgPageName') +              ($h ? '#' + $h .find('.mw-headline') .attr('id') : '')           ) + '&type=login'; }       return $h ? $h .find('.editsection > a') .attr('href') : '?action=edit'; }   });

function Legend ($icons) { this.parsed = {}; this.forceIndex = []; $icons.each(       $.proxy(this.readNote, this)      ); delete this.forceIndex; log(this.parsed); }

$.extend(Legend.prototype, {

isEmpty: function { if (this.empty === undefined) { this.empty = true; for (var i in this.parsed) { if (this.parsed.hasOwnProperty(i)) { this.empty = false; break; }         }        }        return this.empty; },

isCoord: function (n) { return (/^\d{1,2}(?:\.\d)?$/).test(n); },

parseNote: function (node) { var $note = $(node), x, y, title, icon, id, legend;

if (!$note.attr('title')) return false;

x = $note.data('x'); if (!this.isCoord(x)) return false; y = $note.data('y'); if (!this.isCoord(y)) return false;

title = $note.data('title') || '';

icon = $note.data('icon'); if (!icon || !icon.length) return false;

legend = $note.data('legend'); if (!legend || !legend.length) return false;

id = 'mn' + n++; $note.attr('data-note', id);

return { id: id, legend: legend }; },

readNote: function (key, node) { var i, g, legend, hash, colon, note = this.parseNote(node); if (!note) return;

legend = note.legend.split(/\s*;;\s*/); for (i = 0; i < legend.length; i++) { hash = legend[i].split(/\s*##\s*/); if (hash.length === 2) { this.parsed[hash[0]] = this.parsed[hash[0]] || { indexed: {}, named: {} };           g = this.parsed[hash[0]]; g.indexed[hash[1]] = g.indexed[hash[1]] || []; g.indexed[hash[1]].push(note.id); } else { colon = legend[i].split(/\s*::\s*/); if (colon.length === 2) { this.parsed[colon[0]] = this.parsed[colon[0]] || { indexed: {}, named: {} };             g = this.parsed[colon[0]]; if (this.forceIndex.indexOf(colon[1]) !== -1) { g.indexed[colon[1]].push(note.id); } else if (g.named[colon[1]]) { this.forceIndex.push(colon[1]); g.indexed[colon[1]] = g.indexed[colon[1]] || []; g.indexed[colon[1]].push(g.named[colon[1]]); g.indexed[colon[1]].push(note.id); delete g.named[colon[1]]; } else { g.named[colon[1]] = note.id; }           }          }        }      },

renderIndexed: function (key, notes) { var i, node, n;

n = document.createElement('span'); n.setAttribute('class', 'map-subGroup-name'); n.appendChild(         document.createTextNode(key)        );

node = document.createElement('div'); node.setAttribute('class', 'map-subGroup'); node.appendChild(n);

for (i = 0; i < notes.length; i++) { n = document.createElement('span'); n.setAttribute('class', 'map-subGroup-note pseudo-link'); n.setAttribute('data-note', notes[i]); n.appendChild(           document.createTextNode(i + 1)          ); node.appendChild(n); }

return node; },

renderNamed: function (key, value) { var node = document.createElement('div'); node.setAttribute('data-note', value); node.setAttribute('class', 'map-group-note pseudo-link'); node.appendChild(         document.createTextNode(key)        ); return node; },

renderGroup: function (key, list) { var sorted, nodes = [], n;

n = document.createElement('div'); n.setAttribute('class', 'map-group-name') n.appendChild(         document.createTextNode(key)        ); nodes.push(n);

n = document.createElement('div'); n.setAttribute('class', 'map-group') nodes.push(n);

sorted = new SortedObject(list.indexed); while (sorted.next) { n.appendChild(           this.renderIndexed(sorted.key, sorted.val)          ); }

sorted = new SortedObject(list.named); while (sorted.next) { n.appendChild(           this.renderNamed(sorted.key, sorted.val)          ); }

return nodes; },

render: function { var sorted = new SortedObject(this.parsed), nodes = [], n;

while (sorted.next) { nodes = nodes.concat(this.renderGroup(sorted.key, sorted.val)); }

this.$wrapper = $(document.createElement('div')) .addClass('map-legend-wrapper') .append(nodes);

return $(document.createElement('div')) .addClass('map-legend') .append(this.$wrapper); },

addScrollbar: function { this.$wrapper.removeAttr('style'); if (this.$wrapper.height > dimensions.legend.h) { this.$wrapper .css({           width: '255px',            paddingRight: '15px',            maxHeight: (dimensions.legend.h - 2 * LEGEND_PADDING) + 'px'          }); }     }    });

function MapLightbox (data) { this.largeSrc = data.src; this.zoneName = data.zone; this.editLink = data.editLink; this.file    = data.file; this.href    = data.href; this.autoShow = data.autoShow;

if (data.$icons && data.$icons.length) { this.$originalIcons = data.$icons; this.legend = new Legend(data.$icons); }

this.empty = !this.legend || this.legend.isEmpty; }

$.extend(MapLightbox.prototype, {

prepare: function { log('MapLightbox.prepare'); var defer = $.Deferred;

this.prepareHeader; this.prepareLargeMap; if (!this.empty) { this.prepareLegend; }

dimensions.setLegend(this.empty);

return defer.resolve.promise; },

init: function { log('MapLightbox.create');

this.resize;

this.initHeader; this.initLargeMap; if (!this.empty) { this.initLegend; }

var that = this;

this.callbacks = { close:  function  { that.close;   }, resize: function  { that.resize;  }, refresh: function { that.refresh; } };

callbacks.refresh.add(this.callbacks.refresh); callbacks.resize.add(this.callbacks.resize); callbacks.close.add(this.callbacks.close); },

prepareHeader: function { log('MapLightbox.prepareHeader');

this.$coords = $(' ') .addClass('map-coords') .css('display', 'none');

this.$close = $(' ', {          title: 'Close'        }) .addClass('map-close pseudo-link') .text('Close');

this.$scale = $(' ') .addClass('map-scale') .css('display', 'none');

this.$info = $(' ') .addClass('map-info') .append(         $('  ')          .addClass('map-title')          .text(this.zoneName)        ) .append(this.$scale) .append(this.$coords);

this.$buttons = $(' ') .addClass('map-buttons') .append(         $('', { title: mw.html.escape(this.file), href: mw.html.escape(this.href) })         .addClass('map-href')          .text(this.file)        );

if (this.editLink) { this.$buttons .append(           $('', { title: 'Edit Map Notes', href: this.editLink })           .addClass('map-href')            .text('Edit Map Notes')          ) .append(           $('', { title: 'About Map Notes', href: ABOUT_NOTES })           .addClass('map-href')            .text('About Map Notes')          ); }

this.$buttons .append(this.$close);

this.$header = $(' ') .addClass('map-header') .css('display', 'none') .append(this.$info) .append(this.$buttons) .appendTo(document.body); },

initHeader: function { this.$close .click(callbacks.close.fire); },

showNotice: function { if (this.$notice) return;

this.$notice = $(' ') .addClass('map-title') .text('press SPACE to fade map') .css({         position: 'fixed',          left: dimensions.largeMap.x + dimensions.largeMap.w / 20 + 'px',          top:  dimensions.largeMap.y + dimensions.largeMap.h / 10 * 9 + 'px'        });

this.$largeMap .append(this.$notice);

this.clearNotice = $.proxy(this.removeNotice, this); callbacks.close.add(this.clearNotice); callbacks.refresh.add(this.clearNotice); callbacks.resize.add(this.clearNotice);

window.setTimeout($.proxy(this.fadeNotice, this), 3000); },

fadeNotice: function { if (!this.$notice) return; this.$notice .fadeOut(200,         $.proxy(this.removeNotice, this)        ); },

removeNotice: function { if (!this.$notice) return; this.$notice.remove; callbacks.close.remove(this.clearNotice); callbacks.refresh.remove(this.clearNotice); callbacks.resize.remove(this.clearNotice); delete this.$notice; delete this.clearNotice; },

prepareLargeMap: function { log('MapLightbox.prepareLargeMap');

if (this.$originalIcons) { this.$icons = this.$originalIcons .clone .each(function {            var $this = $(this);            $this            .attr({ id:   $this.attr('data-note'), title: $this.attr('original-title') })           .removeAttr('orginal-title');          }); }

this.$image = $(' ', {         src: this.largeSrc        });

this.$largeMap = $(' ') .addClass('map-large') .css('display', 'none') .append(this.$image);

if (this.$icons) { this.$largeMap .append(this.$icons); }

this.$largeMap .appendTo(document.body); },

initLargeMap: function { log('MapLightbox.initLargeMap'); if (this.$icons) { tips.add(this.$icons, 'manual', this.autoShow); }

this.$largeMap .on('mouseenter mousemove', $.proxy(this.updateCoords, this)) .mouseleave($.proxy(this.hideCoords, this));

if (this.$icons) { this.showNotice;

var that = this; $(document.body) .on('keydown.mapLightbox', function (e) {           if (e.which === 32) that.fadeMap;          }) .on('keyup.mapLightbox', function (e) {           if (e.which === 32) that.showMap;          }) .on('keypress.mapLightbox', function (e) {           e.stopImmediatePropagation;            e.preventDefault;          }); }     },

prepareLegend: function { log('MapLightbox.prepareLegend'); this.$legend = this.legend.render .css('display', 'none') .appendTo(document.body); },

initLegend: function { log('MapLightbox.initLegend'); var that = this; this.$legend .find('.pseudo-link') .mouseenter(function {          $(document.getElementById($(this).data('note'))).tipsy('show');        }) .mouseleave(function {          $(document.getElementById($(this).data('note'))).tipsy('hide');        });

this.$legend .find('.map-group-name') .data('opened', true) .css('cursor', 'pointer') .click(function {          var $this = $(this),            move = $this.data('opened') ? 'slideUp' : 'slideDown',            $group = $this.next('.map-group');          $this.data('opened', ! $this.data('opened'));         $group[move](100, function  { that.legend.addScrollbar; });       });      },

formatCoord: function (coord) { var c = Math.round(coord * 10) / 10; c = Math.min(99.9, Math.max(0.1, c)); return Math.round(c) === c ? c + '.0' : c;     },

hideCoords: function { this.$coords.css('display', 'none'); this.showMap; this.showHideButtons; },

fadeMap: function { if (!this.isInCorner) { this.$image.stop.animate({ opacity: 0.25 }, 200); this.isInCorner = true; }     },

showMap: function { if (this.isInCorner) { this.$image.stop.animate({ opacity: 1 }, 200); this.isInCorner = false; }     },

updateCoords: function (e) { var x = (e.clientX - dimensions.largeMap.x) / dimensions.largeMap.w * 100, y = (e.clientY - dimensions.largeMap.y) / dimensions.largeMap.h * 100;

this.$coords .css('display', 'inline') .text(this.formatCoord(x) + ',' + this.formatCoord(y));

this.showHideButtons; },

refresh: function { this.$header .add(this.$largeMap) .add(this.$legend) .css('display', 'none'); },

resize: function { log('MapLightbox.resize'); this.resizePart(this.$header, dimensions.header); this.resizePart(this.$largeMap, dimensions.largeMap); if (!this.empty) { this.resizePart(this.$legend, dimensions.legend); }

this.$image.attr({         width:  dimensions.largeMap.w + 'px',          height: dimensions.largeMap.h + 'px'        });

if (dimensions.scale !== 100) { this.$scale .css('display', 'inline') .text('scale: ' + dimensions.scale + '%'); } else { this.$scale .css('display', 'none'); }

if (this.$legend) { this.legend.addScrollbar; }

this.showHideButtons; },

showHideButtons: function { var infoWidth = this.$info.width, buttonWidth = this.$buttons.removeClass('map-minimal').width;

if (infoWidth + buttonWidth + 20 >= dimensions.largeMap.w) { this.$buttons.addClass('map-minimal'); }     },

resizePart: function (part, values) { part .css({         width: values.w + 'px', height: values.h + 'px',          left:  values.x + 'px', top:    values.y + 'px',          display: 'block'        }); },

close: function { log('MapLightbox.close'); this.$header.remove; this.$largeMap.remove; if (!this.empty) { this.$legend.remove; }

delete this.$info; delete this.$buttons; delete this.$scale; delete this.$coords; delete this.$close; delete this.$header; delete this.$image; delete this.$icons; delete this.$largeMap; if (!this.empty) { delete this.$legend; delete this.legend.$wrapper; }

callbacks.refresh.remove(this.callbacks.refresh); callbacks.resize.remove(this.callbacks.resize); callbacks.close.remove(this.callbacks.close); delete this.callbacks; }   });

var dimensions = ({

header: { h: HEADER_HEIGHT + HEADER_PADDING * 2 // HEADER_PADDING really necessary ??? },

margin: { vertical:  MARGIN_VERTICAL   * 2, horizontal: MARGIN_HORIZONTAL * 2 },

between: { headerMap: MARGIN_INNER },

resetLegend: function { this.legend = { w: COLUMN_WIDTH + COLUMN_PADDING * 2 // COLUMN_PADDING really necessary ??? };       this.between.mapLegend = MARGIN_INNER; },

setLegend: function (empty) { log('dimensions.setLegend', empty); if (empty) { this.legend = { w: 0, h: 0, x: 0, y: 0 }; this.between.mapLegend = 0; } else { this.resetLegend; }       this.calculate; },

calculate: function {

this.win = { w: $(window).width, h: $(window).height };

this.largeMap = { w: Math.min(           MAP_MAX_WIDTH,            this.win.w - this.legend.w - this.between.mapLegend - this.margin.horizontal,            Math.round( Math.min(               MAP_MAX_HEIGHT,                this.win.h - this.header.h - this.between.headerMap - this.margin.vertical              ) * 3 / 2 )         )        };

this.scale = Math.round(this.largeMap.w / MAP_MAX_WIDTH * 100);

if (this.scale < MIN_SCALE) { callbacks.disable.fire; callbacks.close.fire; } else { this.largeMap.h = Math.round(this.largeMap.w * 2 / 3);

this.header.y = Math.round((this.win.h - this.largeMap.h - this.header.h - this.between.headerMap) / 2); this.header.x = Math.round((this.win.w - this.largeMap.w - this.legend.w - this.between.mapLegend) / 2); this.header.w = this.largeMap.w;

this.largeMap.x = this.header.x;         this.largeMap.y = this.header.y + this.header.h + this.between.headerMap;

if (this.legend.w) { this.legend.h = this.largeMap.h + this.header.h + this.between.headerMap; this.legend.x = this.largeMap.x + this.header.w + this.between.mapLegend; this.legend.y = Math.round((this.win.h - this.legend.h) / 2); }

callbacks.enable.fire; }     },

init: function { this.resetLegend; callbacks.refresh.add($.proxy(this.calculate,  this)); callbacks.close .add($.proxy(this.resetLegend, this)); return this; }

}).init;

function isWikiaImage (src) { return src && src.length && /^(?:https?:)?\/\/(images|static|img|vignette)(\d*)\.wikia\.(?:nocookie\.net|com)\//.test(src); }

function isWithinBounds (data, min, max) { return data !== undefined && data !== null && data >= min && data <= max; }

$maps .each(function {      var $map = $(this);      if (!$map.data('map') && isWikiaImage($map.data('small')) && isWikiaImage($map.data('large')) && isWithinBounds($map.data('size'), MAP_MIN_WIDTH, MAP_MAX_WIDTH) ) {       if ($map.hasClass('coords') && isWithinBounds($map.data('x'), 0, 100) && isWithinBounds($map.data('y'), 0, 100) ) {         $map.data('map', new Coords($map));        } else if ($map.hasClass('map-textlink')) {          $map.data('map', new Link($map));        } else if ($map.hasClass('map-embed')) {          $map.data('map', new Embedded($map));        }      }    });

preloader.tipsy .done(function {      dimensions.calculate;    });

$(window) .resize(callbacks.refresh.fire) .resize($.debounce(100, callbacks.resize.fire)); }

$(function {    var $maps = $('.map');    if ($maps.length) {      initMaps($maps);    }  });

}(mediaWiki, jQuery, window, window.document));