-
-
Save darkwing/64eeedfe7484c005bee3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(win, doc, $) { | |
'use strict'; | |
/* | |
Bug 981409 - Add some CSS fallback for browsers without MathML support. | |
This is based on | |
https://developer.mozilla.org/en-US/docs/Web/MathML/Authoring#Fallback_for_Browsers_without)MathML_support | |
and https://github.com/fred-wang/mathml.css. | |
*/ | |
$('math').length && (function() { | |
// Test for MathML support | |
var $div = $('<div class="offscreen"><math xmlns="http://www.w3.org/1998/Math/MathML"><mspace height="23px" width="77px"/></math></div>').appendTo(document.body); | |
var box = $div.get(0).firstChild.firstChild.getBoundingClientRect(); | |
$div.remove(); | |
var supportsMathML = Math.abs(box.height - 23) > 1 || Math.abs(box.width - 77) > 1; | |
if(!supportsMathML) { | |
// Add CSS fallback | |
$('<link href="/media/css/libs/mathml.css" rel="stylesheet" type="text/css" />').appendTo(document.head); | |
// Add notification | |
$('#wikiArticle').prepend('<div class="notice"><p>Your browser does not seem to support MathML. Some CSS fallback will be used instead, but the mathematics on this page might not render correctly.</p></div>'); | |
} | |
})(); | |
/* | |
Togglers within articles (i.e.) | |
*/ | |
$('.toggleable').mozTogglers(); | |
/* | |
Toggle for quick links show/hide | |
*/ | |
(function() { | |
// Set up the quick links for the toggler | |
var $quickLinks = $('#quick-links'); | |
setupTogglers($quickLinks.find('> ul > li, > ol > li')); | |
$quickLinks.find('.toggleable').mozTogglers(); | |
var $columnContainer = $('#wiki-column-container'); | |
var $quickLinksControl = $('#wiki-controls .quick-links'); | |
var child = $('#wiki-left').get(0); | |
if(child) { | |
var parent = child.parentNode; | |
} | |
// Quick Link toggles | |
$('#quick-links-toggle, #show-quick-links').on('click', function(e) { | |
e.preventDefault(); | |
$(child).toggleClass('column-closed'); | |
$columnContainer.toggleClass('wiki-left-closed'); | |
$quickLinksControl.toggleClass('hidden'); | |
if($(child).hasClass('column-closed')) { | |
parent.removeChild(child); | |
} | |
else { | |
parent.appendChild(child); | |
} | |
mdn.analytics.trackEvent(['Wiki sidebar toggle', 'Click', this.id == 'quick-links-toggle' ? 'Hide' : 'Show'], true); | |
}); | |
})(); | |
/* | |
Set up the zone subnav accordion | |
*/ | |
$('.subnav').each(function() { | |
var $subnav = $(this); | |
var $subnavList = $subnav.find(' > ol'); | |
var minHeightFn = $('.zone-landing-header-preview-base').length ? setMinHeight : noop; | |
if(!$subnavList.length) return; // Exit if the subnav isn't set up properly | |
// Set the list items as togglers where needed | |
setupTogglers($subnavList.find('li')); | |
// Make them toggleable! | |
$subnavList.find('.toggleable').mozTogglers({ | |
slideCallback: minHeightFn | |
}); | |
// Try to find the current page in the list, if found, open it | |
// Need to keep track of the elements we've found so they aren't found twice | |
var used = []; | |
var $selected = $subnavList.find('a[href$="' + doc.location.pathname + '"]'); | |
$selected.each(function() { | |
var self = this; | |
var $togglers = $(this).parents('.toggleable').find('.toggler'); | |
$togglers.each(function() { | |
if($.contains($(this).parent('li').get(0), self) && used.indexOf(this) === -1) { | |
$(this).trigger('mdn:click'); | |
used.push(this); | |
} | |
}); | |
}).parent().addClass('current'); | |
// Mark this is an accordion so the togglers open/close properly | |
$subnavList.addClass('accordion'); | |
function noop(){} | |
function setMinHeight() { | |
if($('.zone-landing-header-preview-base').css('position') == 'absolute') { | |
$('.wiki-main-content').css('min-height', $subnav.height()); | |
} | |
} | |
minHeightFn(); | |
}); | |
/* | |
Subscribe / unsubscribe to an article | |
*/ | |
$('.page-watch a').on('click', function(e) { | |
e.preventDefault(); | |
$(this).closest('form').submit(); | |
}); | |
// Utility method for the togglers | |
function setupTogglers($elements) { | |
$elements.each(function() { | |
var $li = $(this); | |
var $sublist = $li.find('> ul, > ol'); | |
if($sublist.length) { | |
$li.addClass('toggleable closed'); | |
$li.find('> a').addClass('toggler').prepend('<i aria-hidden="true" class="icon-caret-up"></i>'); | |
$sublist.addClass('toggle-container'); | |
} | |
}); | |
} | |
/* | |
Add icons to external links if they don't have images | |
*/ | |
$('.external').each(function() { | |
var $link = $(this); | |
if(!$link.find('img').length) $link.addClass('external-icon'); | |
}); | |
/* | |
Syntax highlighting scripts | |
*/ | |
$('article pre').length && ('querySelectorAll' in document) && (function() { | |
var mediaPath = win.mdn.mediaPath; | |
$('<link />').attr({ | |
type: 'text/css', | |
rel: 'stylesheet', | |
href: mediaPath + 'css/syntax-prism-min.css' | |
}).appendTo(doc.head); | |
var syntaxScript = doc.createElement('script'); | |
syntaxScript.setAttribute('data-manual', ''); | |
syntaxScript.async = 'true'; | |
syntaxScript.src = mediaPath + 'js/syntax-prism-min.js'; | |
doc.body.appendChild(syntaxScript); | |
})(); | |
/* | |
Set up the scrolling TOC effect | |
*/ | |
(function() { | |
var $toc = $('#toc'); | |
if($toc.length) { | |
var tocOffset = $toc.offset().top; | |
var $toggler = $toc.find('> .toggler'); | |
var fixedClass = 'fixed'; | |
var $wikiRight = $('#wiki-right'); | |
var scrollFn = debounce(function(e) { | |
// Set forth the pinned or static positioning of the table of contents | |
var scroll = win.scrollY; | |
var maxHeight = win.innerHeight - parseInt($toc.css('padding-top'), 10) - parseInt($toc.css('padding-bottom'), 10); | |
if(scroll > tocOffset && $toggler.css('pointer-events') == 'none') { | |
$toc.css({ | |
width: $toc.css('width'), | |
maxHeight: maxHeight | |
}); | |
if(!$toc.hasClass(fixedClass)){ | |
$toc.addClass(fixedClass); | |
} | |
} | |
else { | |
$toc.css({ | |
width: 'auto', | |
maxHeight: 'none' | |
}); | |
$toc.removeClass(fixedClass); | |
} | |
// Should the TOC be one-column (auto-closed) or sidebar'd | |
if(!e || e.type == 'resize') { | |
if($toggler.css('pointer-events') == 'auto' || $toggler.find('i').css('display') != 'none') { /* icon check is for old IEs that don't support pointer-events */ | |
if(!$toc.attr('data-closed')) { | |
$toggler.trigger('mdn:click'); | |
} | |
} | |
else if($toc.attr('data-closed')) { // Changes width, should be opened (i.e. mobile to desktop width) | |
$toggler.trigger('mdn:click'); | |
} | |
} | |
}, 10); | |
// Set it forth! | |
scrollFn(); | |
$(win).on('scroll', scrollFn); | |
} | |
})(); | |
/* | |
Compat table table setup | |
*/ | |
$('.htab').each(function(index) { | |
var $htab = $(this); | |
var $items = $htab.find('>ul>li'); | |
$htab.append($('div[id=compat-desktop]')[index]); | |
$htab.append($('div[id=compat-mobile]')[index]); | |
$items.find('a').on('click mdn:click', function(e) { | |
var $this = $(this); | |
if(e) { | |
e.preventDefault(); | |
e.stopPropagation(); | |
} | |
$items.removeClass('selected'); | |
$this.parent().addClass('selected'); | |
$htab.find('>div').hide().eq($items.index($this.parent())).show(); | |
}).eq(0).trigger('mdn:click'); | |
}); | |
/* | |
Bottom language checker autosubmit | |
*/ | |
$('.wiki-l10n').on('change', function() { | |
if(this.value) { | |
location = this.value; | |
} | |
}); | |
/* | |
Adds a context menu to edit page or view history | |
*/ | |
$('body[contextmenu=edit-history-menu]').mozContextMenu(function(target, $contextMenu) { | |
var $menuitems = $contextMenu.find('menuitem'); | |
var $body = $('body'); | |
var isTextSelected = !document.getSelection().isCollapsed; | |
var isLinkTargeted = ($(target).is('a') || $(target).parents().is('a')); | |
var isImageTargeted = $(target).is('img'); | |
$body.attr('contextmenu', 'edit-history-menu'); | |
if(isLinkTargeted || isTextSelected || isImageTargeted) { | |
$body.attr('contextmenu', ''); | |
} | |
$contextMenu.on('click', function(e) { | |
location.href = (target.href || location.href) + $(e.target).data('action') + '?src=context'; | |
}); | |
}); | |
/* | |
Stack overflow search form, used for dev program | |
ex: http://stackoverflow.com/search?q=[firefox]+or+[firefox-os]+or+[html5-apps]+foobar | |
*/ | |
$('.stack-form').html('<form action="http://stackoverflow.com/search"><i class="stack-icon" aria-hidden="true"></i><label for="stack-search" class="offscreen">' + gettext('Search Stack Overflow') + '</label><input id="stack-search" placeholder="' + gettext('Search Stack Overflow') + '" /><button type="submit" class="offscreen">Submit Search</button></form>').find('form').on('submit', function(e) { | |
e.preventDefault(); | |
var value = $(this).find('#stack-search').val(); | |
if(value != '') { | |
win.location = 'http://stackoverflow.com/search?q=[firefox]+or+[firefox-os]+or+[html5-apps]+' + value; | |
} | |
}); | |
/* | |
if many contributors, dont show all at once. | |
*/ | |
(function (){ | |
var $contributors = $('.contributor-avatars'); | |
var $contributorsList = $contributors.find('ul'); | |
$contributors.find('a').each(function(index) { | |
$(this).on('click', function(e) { | |
var newTab = (e.metaKey || e.ctrlKey); | |
var href = this.href; | |
var callback = function() { | |
location = href; | |
}; | |
var data = ['Top Contributors', 'Click position', index]; | |
if (newTab) { | |
mdn.analytics.trackEvent(data); | |
} else { | |
e.preventDefault(); | |
mdn.analytics.trackEvent(data, callback); | |
} | |
}); | |
}); | |
$contributorsList.on('focusin focusout', function(e) { | |
if (e.type === 'focusin') { | |
$(this).addClass('focused'); | |
} else { | |
$(this).removeClass('focused'); | |
} | |
}); | |
if ($contributors.find('li').length > 13) { | |
var showAllContributors = $('<button type="button" class="transparent">Show all…<span class="hidden"> contributors</span></button>'); | |
showAllContributors.on('click keypress', function(e) { | |
var enterOrSpace = (e.which === 13 || e.which === 32); | |
if (enterOrSpace || e.type === 'click') { | |
e.preventDefault(); | |
mdn.analytics.trackEvent(['Top Contributors', 'Show all']); | |
$contributors.find('li.hidden').removeClass('hidden'); | |
$contributors.find('noscript').mozLazyloadImage(); | |
if (enterOrSpace) { | |
$contributors.find('li:eq(13) a').focus(); | |
} | |
$(this).remove(); | |
} | |
}); | |
$contributors.find('li:lt(13) noscript').mozLazyloadImage(); | |
$contributors.find('li:gt(12)').addClass('hidden'); | |
$contributorsList.after(showAllContributors); | |
} else { | |
$contributors.find('noscript').mozLazyloadImage(); | |
} | |
})(); | |
/* | |
jQuery extensions used within the wiki. | |
*/ | |
$.extend({ | |
// Currently used within CKEDitor YouTube plugin | |
parseQuerystring: function(str){ | |
var nvpair = {}; | |
var qs = (str || location.search).replace('?', ''); | |
var pairs = qs.split('&'); | |
$.each(pairs, function(i, v){ | |
var pair = v.split('='); | |
nvpair[pair[0]] = pair[1]; | |
}); | |
return nvpair; | |
}, | |
// Used within the wiki new/move pages | |
slugifyString: function(str, allowSlash) { | |
var regex = new RegExp('[\?\&\"\'\#\*\$' + (allowSlash ? '' : '\/') + ' +?]', 'g'); | |
// Remove anything from the slug that could cause big problems | |
return str.replace(regex, '_') | |
// "$" is used for verb delimiter in URLs | |
.replace(/\$/g, '') | |
// Don't allow "_____" mess | |
.replace(/\_+/g, '_'); | |
} | |
}); | |
function debounce(func, wait, immediate) { | |
var timeout; | |
return function() { | |
var context = this, args = arguments; | |
var later = function() { | |
timeout = null; | |
if (!immediate) func.apply(context, args); | |
}; | |
var callNow = immediate && !timeout; | |
clearTimeout(timeout); | |
timeout = setTimeout(later, wait); | |
if (callNow) func.apply(context, args); | |
}; | |
} | |
})(window, document, jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment