2015-11-13 19:10:23 +00:00
|
|
|
window.common = (function(global) {
|
|
|
|
const {
|
2015-11-20 01:27:05 +00:00
|
|
|
Rx: { Subject, Observable },
|
2015-11-13 19:10:23 +00:00
|
|
|
CodeMirror,
|
|
|
|
emmetCodeMirror,
|
2016-01-11 00:54:26 +00:00
|
|
|
Clipboard,
|
2015-11-13 19:10:23 +00:00
|
|
|
common = { init: [] }
|
|
|
|
} = global;
|
|
|
|
|
2015-11-20 01:27:05 +00:00
|
|
|
const { challengeType = '0', challengeTypes } = common;
|
2015-11-18 05:25:16 +00:00
|
|
|
|
|
|
|
if (
|
|
|
|
!CodeMirror ||
|
2015-11-20 05:51:38 +00:00
|
|
|
challengeType === challengeTypes.BASEJUMP ||
|
2015-11-20 01:27:05 +00:00
|
|
|
challengeType === challengeTypes.ZIPLINE ||
|
|
|
|
challengeType === challengeTypes.VIDEO ||
|
|
|
|
challengeType === challengeTypes.STEP ||
|
|
|
|
challengeType === challengeTypes.HIKES
|
2015-11-18 05:25:16 +00:00
|
|
|
) {
|
|
|
|
common.editor = {};
|
|
|
|
return common;
|
2015-11-13 19:10:23 +00:00
|
|
|
}
|
|
|
|
|
2015-11-18 05:25:16 +00:00
|
|
|
var editor = CodeMirror.fromTextArea(
|
|
|
|
document.getElementById('codeEditor'),
|
|
|
|
{
|
|
|
|
lint: true,
|
|
|
|
lineNumbers: true,
|
|
|
|
mode: 'javascript',
|
|
|
|
theme: 'monokai',
|
|
|
|
runnable: true,
|
|
|
|
matchBrackets: true,
|
|
|
|
autoCloseBrackets: true,
|
|
|
|
scrollbarStyle: 'null',
|
|
|
|
lineWrapping: true,
|
|
|
|
gutters: ['CodeMirror-lint-markers']
|
|
|
|
}
|
|
|
|
);
|
2015-11-13 19:10:23 +00:00
|
|
|
|
2016-01-16 06:49:44 +00:00
|
|
|
var clipboard = new Clipboard('.copy-btn', {
|
2016-01-11 00:54:26 +00:00
|
|
|
text: function(trigger) {
|
|
|
|
var type;
|
|
|
|
switch (common.challengeType) {
|
|
|
|
case common.challengeTypes.HTML:
|
|
|
|
type = 'html';
|
|
|
|
break;
|
|
|
|
case common.challengeTypes.JS:
|
|
|
|
case common.challengeTypes.BONFIRE:
|
2016-01-16 05:42:57 +00:00
|
|
|
type = 'js';
|
2016-01-11 00:54:26 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
type = '';
|
|
|
|
}
|
|
|
|
|
|
|
|
var returnValue = '';
|
2016-01-16 05:42:57 +00:00
|
|
|
switch (trigger.id) {
|
|
|
|
case 'markdown':
|
|
|
|
returnValue = '```' + type + '\n' + editor.getSelection() + '\n```';
|
|
|
|
editor.replaceSelection(editor.getSelection());
|
|
|
|
return returnValue;
|
|
|
|
case 'plain':
|
|
|
|
returnValue = editor.getSelection();
|
|
|
|
editor.replaceSelection(editor.getSelection());
|
|
|
|
return returnValue;
|
|
|
|
case 'link':
|
2016-01-16 06:49:44 +00:00
|
|
|
default:
|
2016-01-16 05:42:57 +00:00
|
|
|
editor.replaceSelection(editor.getSelection());
|
|
|
|
return '[Challenge - ' + common.challengeName +
|
|
|
|
(common.username ? ' (' + common.username + '\'s solution)' : '')
|
|
|
|
+ '](' + String(window.location).replace(/\)/g, '%29') + ')';
|
2016-01-11 00:54:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
common.clipboard = clipboard;
|
|
|
|
|
2016-01-16 06:49:44 +00:00
|
|
|
var copyButton = `<a id="copy-btn-parent" href="/" data-toggle="popover" \
|
|
|
|
data-trigger="manual" data-content="<a class='copy-btn' id='link' href='/' \
|
2016-01-11 00:54:26 +00:00
|
|
|
data-toggle='popover' data-trigger='manual' \
|
2016-01-16 06:49:44 +00:00
|
|
|
title='Copy the link to this challenge'>Copy Link</a><br><a class='copy-btn' \
|
2016-01-11 00:54:26 +00:00
|
|
|
id='markdown' href='/' data-toggle='popover'\ data-trigger='manual' \
|
|
|
|
title='Copy the contents of code editor with Markdown syntax \
|
2016-01-16 06:49:44 +00:00
|
|
|
highlighting'>Copy as Pretty Code</a><br><a class='copy-btn' id='plain' \
|
2016-01-11 00:54:26 +00:00
|
|
|
href='/' data-toggle='popover' data-trigger='manual' title='Copy the \
|
|
|
|
contents of code editor'>Copy as Plain Code</a>"></a>`;
|
|
|
|
|
2016-01-16 06:49:44 +00:00
|
|
|
var left = -5, top = -5;
|
2016-01-11 00:54:26 +00:00
|
|
|
$(document).mousemove(function(event) {
|
|
|
|
left = event.pageX;
|
|
|
|
top = event.pageY;
|
|
|
|
});
|
|
|
|
|
2016-01-16 06:49:44 +00:00
|
|
|
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);
|
2016-01-11 00:54:26 +00:00
|
|
|
}
|
2016-01-16 06:49:44 +00:00
|
|
|
};
|
|
|
|
var callNow = immediate && !timeout;
|
|
|
|
clearTimeout(timeout);
|
|
|
|
timeout = setTimeout(later, wait);
|
|
|
|
if (callNow) {
|
|
|
|
func.apply(context, args);
|
2016-01-11 00:54:26 +00:00
|
|
|
}
|
2016-01-16 06:49:44 +00:00
|
|
|
};
|
2016-01-11 00:54:26 +00:00
|
|
|
}
|
|
|
|
|
2016-01-16 06:49:44 +00:00
|
|
|
var showPopover = debounce(function() {
|
|
|
|
if (editor.somethingSelected()) {
|
|
|
|
$('#copy-btn-parent').popover('show');
|
|
|
|
var editorOffset = $('#mainEditorPanel > form.code').offset(),
|
|
|
|
editorHeight = $('#mainEditorPanel > form.code').height(),
|
|
|
|
editorWidth = $('#mainEditorPanel > form.code').width(),
|
|
|
|
theHeight = $('.popover').height(),
|
|
|
|
theWidth = $('.popover').width();
|
|
|
|
if ((left < editorOffset.left
|
|
|
|
|| left > editorOffset.left + editorWidth - theWidth) || left === -5) {
|
|
|
|
left = (editorOffset.left + editorWidth) / 2;
|
|
|
|
}
|
|
|
|
if ((top < editorOffset.top
|
|
|
|
|| top > editorOffset.top + editorHeight - theHeight) || top === -5) {
|
|
|
|
top = (editorOffset.top + editorHeight) / 2;
|
|
|
|
}
|
|
|
|
$('.popover').css('left', (left + 10) + 'px');
|
|
|
|
$('.popover').css('top', (top - (theHeight / 2) - 7) + 'px');
|
|
|
|
}
|
|
|
|
}, 250);
|
|
|
|
|
2016-01-11 00:54:26 +00:00
|
|
|
if (
|
|
|
|
challengeType === challengeTypes.HTML ||
|
|
|
|
challengeType === challengeTypes.JS ||
|
|
|
|
challengeType === challengeTypes.BONFIRE
|
|
|
|
) {
|
|
|
|
|
|
|
|
$('body').append(copyButton);
|
2016-01-16 06:49:44 +00:00
|
|
|
$('#copy-btn-parent').popover({html: true});
|
2016-01-11 00:54:26 +00:00
|
|
|
|
|
|
|
CodeMirror.on(document, 'mousedown', function() {
|
2016-01-16 06:49:44 +00:00
|
|
|
$('#copy-btn-parent').popover('hide');
|
2016-01-11 00:54:26 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
CodeMirror.on(document, 'mouseup', showPopover);
|
|
|
|
|
2016-01-16 06:49:44 +00:00
|
|
|
$(document).on('click', '.copy-btn', function(e) {
|
2016-01-11 00:54:26 +00:00
|
|
|
e.preventDefault();
|
2016-01-16 06:49:44 +00:00
|
|
|
$('#copy-btn-parent').popover('hide');
|
2016-01-11 00:54:26 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2015-11-13 19:10:23 +00:00
|
|
|
editor.setSize('100%', 'auto');
|
|
|
|
|
2015-11-22 04:30:30 +00:00
|
|
|
common.editorExecute$ = new Subject();
|
2015-11-20 01:27:05 +00:00
|
|
|
common.editorKeyUp$ = Observable.fromEventPattern(
|
2015-11-22 04:30:30 +00:00
|
|
|
(handler) => editor.on('keyup', handler),
|
|
|
|
(handler) => editor.off('keyup', handler)
|
2015-11-20 01:27:05 +00:00
|
|
|
);
|
2015-11-13 19:10:23 +00:00
|
|
|
|
|
|
|
editor.setOption('extraKeys', {
|
|
|
|
Tab: function(cm) {
|
|
|
|
if (cm.somethingSelected()) {
|
|
|
|
cm.indentSelection('add');
|
|
|
|
} else {
|
|
|
|
var spaces = Array(cm.getOption('indentUnit') + 1).join(' ');
|
|
|
|
cm.replaceSelection(spaces);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'Shift-Tab': function(cm) {
|
|
|
|
if (cm.somethingSelected()) {
|
|
|
|
cm.indentSelection('subtract');
|
|
|
|
} else {
|
|
|
|
var spaces = Array(cm.getOption('indentUnit') + 1).join(' ');
|
|
|
|
cm.replaceSelection(spaces);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'Ctrl-Enter': function() {
|
2015-11-20 01:27:05 +00:00
|
|
|
common.editorExecute$.onNext();
|
2015-11-13 19:10:23 +00:00
|
|
|
return false;
|
|
|
|
},
|
|
|
|
'Cmd-Enter': function() {
|
2015-11-20 01:27:05 +00:00
|
|
|
common.editorExecute$.onNext();
|
2015-11-13 19:10:23 +00:00
|
|
|
return false;
|
2016-01-11 00:54:26 +00:00
|
|
|
},
|
|
|
|
'Ctrl-A': function(cm) {
|
|
|
|
cm.execCommand('selectAll');
|
|
|
|
showPopover();
|
|
|
|
},
|
|
|
|
'Cmd-A': function(cm) {
|
|
|
|
cm.execCommand('selectAll');
|
|
|
|
showPopover();
|
2015-11-13 19:10:23 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
var info = editor.getScrollInfo();
|
|
|
|
|
|
|
|
var after = editor.charCoords({
|
|
|
|
line: editor.getCursor().line + 1,
|
|
|
|
ch: 0
|
|
|
|
}, 'local').top;
|
|
|
|
|
|
|
|
if (info.top + info.clientHeight < after) {
|
|
|
|
editor.scrollTo(null, after - info.clientHeight + 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (emmetCodeMirror) {
|
|
|
|
emmetCodeMirror(
|
|
|
|
editor,
|
|
|
|
{
|
|
|
|
'Cmd-E': 'emmet.expand_abbreviation',
|
|
|
|
Tab: 'emmet.expand_abbreviation_with_tab',
|
|
|
|
Enter: 'emmet.insert_formatted_line_break_only'
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
common.init.push(function() {
|
2015-11-20 01:27:05 +00:00
|
|
|
let editorValue;
|
2015-11-13 19:10:23 +00:00
|
|
|
if (common.codeUri.isAlive()) {
|
|
|
|
editorValue = common.codeUri.parse();
|
|
|
|
} else {
|
2015-11-22 04:30:30 +00:00
|
|
|
editorValue = common.codeStorage.isAlive(common.challengeName) ?
|
|
|
|
common.codeStorage.getStoredValue(common.challengeName) :
|
2015-11-13 19:10:23 +00:00
|
|
|
common.seed;
|
|
|
|
}
|
|
|
|
|
|
|
|
editor.setValue(common.replaceSafeTags(editorValue));
|
|
|
|
editor.refresh();
|
|
|
|
});
|
|
|
|
|
|
|
|
common.editor = editor;
|
|
|
|
|
|
|
|
return common;
|
|
|
|
}(window));
|