Permalink
var main = window.main || {}; | |
main.mapShareKey = 'map-shares'; | |
main.ga = window.ga || function() {}; | |
main = (function(main, global) { | |
const { Mousetrap } = global; | |
// should be set before gitter script loads | |
((window.gitter = {}).chat = {}).options = { | |
disableDefaultChat: true | |
}; | |
// wait for sidecar to load | |
main.chat = {}; | |
main.chat.isOpen = false; | |
main.chat.createHelpChat = function createHelpChat() { | |
throw new Error('Sidecar chat has not initialized'); | |
}; | |
document.addEventListener('gitter-sidecar-ready', function(e) { | |
main.chat.GitterChat = e.detail.Chat; | |
main.chat.createHelpChat = function(room, helpChatBtnClass, roomTitle) { | |
// room is always in PascalCase | |
roomTitle = room | |
.replace(/([A-Z])/g, ' $1') | |
.replace('Java Script', 'JavaScript'); | |
$('body').append( | |
'<aside id="chat-embed-help" class="gitter-chat-embed is-collapsed" />' | |
); | |
main.chat.helpChat = new main.chat.GitterChat({ | |
room: `freecodecamp/${room}`, | |
activationElement: false, | |
targetElement: $('#chat-embed-help') | |
}); | |
$(helpChatBtnClass).on('click', function() { | |
// is button already pressed? | |
// no? open chat | |
// yes? close chat | |
var shouldChatBeOpen = !$(this).hasClass('active'); | |
main.chat.helpChat.toggleChat(shouldChatBeOpen); | |
if (shouldChatBeOpen) { | |
$(helpChatBtnClass).addClass('active'); | |
} | |
}); | |
var helpTitleAdd = false; | |
$('#chat-embed-help').on('gitter-chat-toggle', function(e) { | |
var shouldButtonBePressed = !!e.originalEvent.detail.state; | |
if (!helpTitleAdd) { | |
helpTitleAdd = true; | |
$('#chat-embed-help > .gitter-chat-embed-action-bar').prepend( | |
'<div class="chat-embed-main-title">' + | |
'<span>' + | |
roomTitle + | |
'</span>' + | |
'</div>' | |
); | |
} | |
if (shouldButtonBePressed) { | |
return $(helpChatBtnClass).addClass('active'); | |
} | |
return $(helpChatBtnClass).removeClass('active'); | |
}); | |
}; | |
$('body').append( | |
'<aside id="chat-embed-main" class="gitter-chat-embed is-collapsed" />' | |
); | |
main.chat.mainChat = new main.chat.GitterChat({ | |
room: 'freecodecamp/freecodecamp', | |
activationElement: false, | |
targetElement: $('#chat-embed-main') | |
}); | |
var mainChatTitleAdded = false; | |
$('#chat-embed-main').on('gitter-chat-toggle', function() { | |
if (mainChatTitleAdded) { | |
return null; | |
} | |
mainChatTitleAdded = true; | |
$('#chat-embed-main > .gitter-chat-embed-action-bar').prepend( | |
'<div class="chat-embed-main-title">' + | |
'<span>Free Code Camp\'s Main Chat</span>' + | |
'</div>' | |
); | |
return null; | |
}); | |
$('#nav-chat-btn').on('click', toggleMainChat); | |
function showMainChat() { | |
if (!main.chat.isOpen) { | |
main.chat.mainChat.toggleChat(true); | |
} | |
} | |
function collapseMainChat() { | |
$('#chat-embed-main').addClass('is-collapsed'); | |
document.activeElement.blur(); | |
} | |
function toggleMainChat() { | |
var isCollapsed = $('#chat-embed-main').hasClass('is-collapsed'); | |
if (isCollapsed) { | |
showMainChat(); | |
} else { | |
collapseMainChat(); | |
} | |
} | |
// keyboard shortcuts: open main chat | |
Mousetrap.bind('g c', toggleMainChat); | |
}); | |
return main; | |
}(main, window)); | |
var lastCompleted = typeof lastCompleted !== 'undefined' ? | |
lastCompleted : | |
''; | |
main.getMapShares = function getMapShares() { | |
var alreadyShared = JSON.parse( | |
localStorage.getItem(main.mapShareKey) || | |
'[]' | |
); | |
if (!alreadyShared || !Array.isArray(alreadyShared)) { | |
localStorage.setItem(main.mapShareKey, JSON.stringify([])); | |
alreadyShared = []; | |
} | |
return alreadyShared; | |
}; | |
main.setMapShare = function setMapShare(id) { | |
var alreadyShared = main.getMapShares(); | |
var found = false; | |
alreadyShared.forEach(function(_id) { | |
if (_id === id) { | |
found = true; | |
} | |
}); | |
if (!found) { | |
alreadyShared.push(id); | |
} | |
localStorage.setItem(main.mapShareKey, JSON.stringify(alreadyShared)); | |
return alreadyShared; | |
}; | |
$(document).ready(function() { | |
var CSRF_HEADER = 'X-CSRF-Token'; | |
var setCSRFToken = function(securityToken) { | |
jQuery.ajaxPrefilter(function(options, _, xhr) { | |
if (!xhr.crossDomain) { | |
xhr.setRequestHeader(CSRF_HEADER, securityToken); | |
} | |
}); | |
}; | |
setCSRFToken($('meta[name="csrf-token"]').attr('content')); | |
$('img').error(function() { | |
$(this) | |
.unbind('error') | |
.attr( | |
'src', | |
'https://s3.amazonaws.com/freecodecamp/camper-image-placeholder.png' | |
); | |
}); | |
function upvoteHandler(e) { | |
e.preventDefault(); | |
var upvoteBtn = this; | |
var id = upvoteBtn.id; | |
var upVotes = $(upvoteBtn).data().upVotes; | |
var username = typeof username !== 'undefined' ? username : ''; | |
var alreadyUpvoted = false; | |
for (var i = 0; i < upVotes.length; i++) { | |
if (upVotes[i].upVotedBy === username) { | |
alreadyUpvoted = true; | |
break; | |
} | |
} | |
if (!alreadyUpvoted) { | |
$.post('/stories/upvote', { id: id }) | |
.fail(function() { | |
$(upvoteBtn).bind('click', upvoteHandler); | |
}) | |
.done(function(data) { | |
$(upvoteBtn) | |
.text('Upvoted!') | |
.addClass('disabled'); | |
$('#storyRank').text(data.rank + ' points'); | |
}); | |
} | |
} | |
$('#story-list').on('click', 'button.btn-upvote', upvoteHandler); | |
var storySubmitButtonHandler = function storySubmitButtonHandler() { | |
if (!$('#story-submission-form')[0].checkValidity()) { | |
return null; | |
} | |
var link = $('#story-url').val(); | |
var headline = $('#story-title').val(); | |
var description = $('#description-box').val(); | |
var data = { | |
data: { | |
link: link, | |
headline: headline, | |
timePosted: Date.now(), | |
description: description, | |
storyMetaDescription: main.storyMetaDescription, | |
rank: 1, | |
image: main.storyImage | |
} | |
}; | |
$('#story-submit').unbind('click'); | |
return $.post('/stories/', data) | |
.fail(function() { | |
$('#story-submit').bind('click', storySubmitButtonHandler); | |
}) | |
.done(function({ storyLink, isBanned }) { | |
if (isBanned) { | |
window.location = '/news'; | |
return null; | |
} | |
window.location = '/stories/' + storyLink; | |
return null; | |
}); | |
}; | |
$('#story-submit').on('click', storySubmitButtonHandler); | |
// map sharing | |
var alreadyShared = main.getMapShares(); | |
if (lastCompleted && alreadyShared.indexOf(lastCompleted) === -1) { | |
$('div[id="' + lastCompleted + '"]') | |
.parent() | |
.parent() | |
.removeClass('hidden'); | |
} | |
// on map view | |
$('.map-challenge-block-share').on('click', function(e) { | |
e.preventDefault(); | |
var challengeBlockName = $(this).children().attr('id'); | |
var challengeBlockEscapedName = challengeBlockName.replace(/\s/, '%20'); | |
var username = typeof window.username !== 'undefined' ? | |
window.username : | |
''; | |
var link = 'https://www.facebook.com/dialog/feed?' + | |
'app_id=1644598365767721' + | |
'&display=page&' + | |
'caption=I%20just%20completed%20the%20' + | |
challengeBlockEscapedName + | |
'%20section%20on%20Free%20Code%20Camp%2E' + | |
'&link=http%3A%2F%2Ffreecodecamp%2Ecom%2F' + | |
username + | |
'&redirect_uri=http%3A%2F%2Ffreecodecamp%2Ecom%2Fmap'; | |
main.setMapShare(challengeBlockName); | |
window.ga('send', 'event', 'FB_LINK', 'SHARE', 'Facebook map share'); | |
window.location.href = link; | |
}); | |
function expandCaret(item) { | |
$(item) | |
.prev().find('.fa-caret-right') | |
.removeClass('fa-caret-right').addClass('fa-caret-down'); | |
} | |
function collapseCaret(item) { | |
$(item) | |
.prev().find('.fa-caret-down') | |
.removeClass('fa-caret-down').addClass('fa-caret-right'); | |
} | |
function expandBlock(item) { | |
$(item).addClass('in').css('height', 'auto'); | |
expandCaret(item); | |
} | |
function collapseBlock(item) { | |
$(item).removeClass('in').css('height', 'auto'); | |
collapseCaret(item); | |
} | |
$.each($('.sr-only'), function(i, span) { | |
if ($(span).text() === ' Complete') { | |
$(span).parents('p').addClass('manip-hidden'); | |
} | |
}); | |
$.each($('.map-collapse'), function(i, div) { | |
if ($(div).find('.manip-hidden').length === | |
$(div).find('p').length) { | |
collapseBlock(div); | |
$(div).prev('h3').addClass('faded'); | |
$(div).prev('h2').addClass('faded'); | |
} | |
}); | |
var scrollTo, dashedName = localStorage.getItem('currentDashedName'), | |
elemsToSearch = $('p.padded-ionic-icon a'), currOrLastChallenge; | |
if (!dashedName && $('.sr-only').length) { | |
elemsToSearch = $('.sr-only'); | |
} | |
currOrLastChallenge = elemsToSearch.filter(function() { | |
if (dashedName) { | |
return $(this).attr('href').match(dashedName); | |
} | |
return $(this).text() === ' Complete'; | |
}); | |
if (currOrLastChallenge.length) { | |
currOrLastChallenge = currOrLastChallenge[currOrLastChallenge.length - 1]; | |
scrollTo = $(currOrLastChallenge).offset().top - 380; | |
$('html, body, .map-accordion').scrollTop(scrollTo); | |
} | |
if (String(window.location).match(/\/map$/ig)) { | |
$('body>.flashMessage').find('.alert').css('display', 'none'); | |
$('.map-fixed-header').css('top', '50px'); | |
} | |
// map global selectors | |
var mapFilter = $('#map-filter'); | |
var mapShowAll = $('#showAll'); | |
$('#nav-map-btn').on('click', toggleMap); | |
$('.map-aside-action-collapse').on('click', collapseMap); | |
function showMap() { | |
if (!main.isMapAsideLoad) { | |
var mapAside = $('<iframe>'); | |
mapAside.attr({ | |
src: '/map-aside', | |
frameBorder: '0' | |
}); | |
$('.map-aside').append(mapAside); | |
main.isMapAsideLoad = true; | |
} | |
$('.map-aside').removeClass('is-collapsed'); | |
} | |
function collapseMap() { | |
$('.map-aside').addClass('is-collapsed'); | |
document.activeElement.blur(); | |
} | |
function toggleMap() { | |
var isCollapsed = $('.map-aside').hasClass('is-collapsed'); | |
if (isCollapsed) { | |
showMap(); | |
} else { | |
collapseMap(); | |
} | |
} | |
$('#nav-wiki-btn').on('click', toggleWiki); | |
$('.wiki-aside-action-collapse').on('click', collapseWiki); | |
function showWiki() { | |
if (!main.isWikiAsideLoad) { | |
var lang = window.location.toString().match(/\/\w{2}\//); | |
lang = (lang) ? lang[0] : '/en/'; | |
var wikiURL = '//freecodecamp.github.io/wiki' + lang; | |
var wikiAside = $('<iframe>'); | |
wikiAside.attr({ | |
src: wikiURL, | |
frameBorder: '0' | |
}); | |
$('.wiki-aside').append(wikiAside); | |
main.isWikiAsideLoad = true; | |
} | |
$('.wiki-aside').removeClass('is-collapsed'); | |
} | |
function collapseWiki() { | |
$('.wiki-aside').addClass('is-collapsed'); | |
document.activeElement.blur(); | |
} | |
function toggleWiki() { | |
var isCollapsed = $('.wiki-aside').hasClass('is-collapsed'); | |
if (isCollapsed) { | |
showWiki(); | |
} else { | |
collapseWiki(); | |
} | |
} | |
$('#accordion').on('show.bs.collapse', function(e) { | |
expandCaret(e.target); | |
if ($('a[data-toggle=collapse]').length === $('.fa-caret-down').length) { | |
mapShowAll.text('Collapse all challenges'); | |
mapShowAll.addClass('active'); | |
} | |
}).on('hide.bs.collapse', function(e) { | |
collapseCaret(e.target); | |
if ($('a[data-toggle=collapse]').length === $('.fa-caret-right').length) { | |
mapShowAll.text('Expand all challenges'); | |
mapShowAll.removeClass('active'); | |
} | |
}); | |
mapShowAll.on('click', () => { | |
var mapExpanded = mapShowAll.hasClass('active'); | |
if (!mapExpanded) { | |
$.each($('.map-collapse:not(".in")'), | |
function(i, div) { | |
expandBlock(div); | |
}); | |
mapShowAll.text('Collapse all challenges'); | |
return mapShowAll.addClass('active'); | |
} else { | |
$.each($('.map-collapse.in'), function(i, div) { | |
collapseBlock(div); | |
}); | |
mapShowAll.text('Expand all challenges'); | |
return mapShowAll.removeClass('active'); | |
} | |
}); | |
// Map live filter | |
mapFilter.on('keyup', () => { | |
if (mapFilter.val().length > 0) { | |
var regex = new RegExp(mapFilter.val().replace(/ /g, '.'), 'i'); | |
// Hide/unhide challenges that match the regex | |
$('.challenge-title').each((index, title) => { | |
if (regex.test($(title).attr('name'))) { | |
expandBlock($(title).closest('.chapterBlock')); | |
expandBlock($(title).closest('.certBlock')); | |
$(title).removeClass('hidden'); | |
} else { | |
$(title).addClass('hidden'); | |
} | |
}); | |
// Hide/unhide blocks with no matches | |
$.each($('.chapterBlock'), function(i, div) { | |
if ($(div).find('.hidden').length === | |
$(div).find('p').length) { | |
$(div).addClass('hidden'); | |
$(div).prev('h3').addClass('hidden'); | |
} else { | |
$(div).removeClass('hidden'); | |
$(div).prev('h3').removeClass('hidden'); | |
} | |
}); | |
// Hide/unhide superblocks with no matches | |
$.each($('.certBlock'), function(i, div) { | |
if ($(div).children('#nested').children('h3.hidden').length === | |
$(div).children('#nested').children('h3').length) { | |
$(div).prev('h2').addClass('hidden'); | |
} else { | |
$(div).prev('h2').removeClass('hidden'); | |
} | |
}); | |
// Display "Clear Filter" element | |
if (mapFilter.next().children().hasClass('fa-search')) { | |
mapFilter.next() | |
.children() | |
.removeClass('fa-search') | |
.addClass('fa-times'); | |
mapFilter.next().addClass('filled'); | |
// Scroll to the top of the page | |
$('html, body, .map-accordion').scrollTop(0); | |
} | |
} else { | |
clearMapFilter(); | |
} | |
// Display not found if everything is hidden | |
if ($.find('.certBlock').length === | |
$('.map-accordion').children('.hidden').length) { | |
$('#noneFound').show(); | |
} else { | |
$('#noneFound').hide(); | |
} | |
}); | |
// Give focus to the search box by default | |
mapFilter.focus(); | |
// Clicking the search button or x clears the map | |
$('.map-buttons .input-group-addon').on('click', clearMapFilter); | |
function clearMapFilter() { | |
mapFilter.val(''); | |
mapFilter.next().children().removeClass('fa-times').addClass('fa-search'); | |
mapFilter.next().removeClass('filled'); | |
$('.map-accordion').find('.hidden').removeClass('hidden'); | |
$('#noneFound').hide(); | |
} | |
// Clear the search on escape key | |
mapFilter.on('keydown', (e) => { | |
if (e.keyCode === 27) { | |
e.preventDefault(); | |
clearMapFilter(); | |
} | |
}); | |
window.Mousetrap.bind('esc', clearMapFilter); | |
// keyboard shortcuts: open map | |
window.Mousetrap.bind('g m', toggleMap); | |
}); |